网络编程
位置:首页>> 网络编程>> Python编程>> Python相互导入的问题解决

Python相互导入的问题解决

作者:__程序喵__  发布时间:2022-12-04 16:59:56 

标签:Python,导入

前言

Hi! 这是随笔专栏的第一篇文章。好的开始等于成功了一半。在之后的日子里,除了不定期分享实战中可总结出的小项目外,还会经常与大分享开发时遇到的问题。今天,是一个曾困扰了我许久的关于 Python 两个文件间互相 import 的问题。

问题→解决

问题描述

两个文件间相互导入时产生了一系列错误,比如 ImportError, NameError 等等。这次,我用简单的代码示例复现一下这些问题,并一步一步解决。

问题复现

这里,我创建两个同目录下的 Python 文件:mutualImportA 和 mutualImportB 并输入代码。

# mutualImportA.py  

from mutualImportB import b

a = 1  

def pA():  
   print(b)  

pA()
# mutualImportB.py  

from mutualImportA import a  

b = 1  

def pB():  
   print(a)  

pB()

创建完毕后,任意运行 A 或 B 都会报错:ImportError: cannot import name 'b' from partially initialized module 'mutualImportB' (most likely due to a circular import)当然有些人习惯于用 import 的导入而非 from import 的导入方式,这时候的报错就会变成:AttributeError: partially initialized module 'mutualImportB' has no attribute 'b' (most likely due to a circular import)

好的,这两个报错还算友好。这种导入的方式都在程序出指明了导入的内容,所以解释器可以发现这里是循环导入(most likely due to a circular import)。但有时出现的 NameError 才真正让人头疼。

我们将代码改一下,保留 from import 语句,但将其 import 后面的变量名改为通配符 * 。这次的报错:
NameError: name 'b' is not defined

这就很奇怪了。我们在使用 IDE 时, IDE 不会检出相互导入时引发的循环导入问题。不过前两种在报错中即可看出,而这时,从报错中很难发现为何 b 没有声明。这种专为复现而出现的小文件中问题可以捋清思路、找到问题,在较大的项目中就往往无从下手了。

那么为什么会出现这样的情况呢?我们想一下整个程序的运行流程。

Python相互导入的问题解决

问题复现完毕,下面探讨如何解决问题。

解决问题

此前,我曾在许多平台看到过文章,但其中绝大部分都是完全重复的(尤其在 CSDN 上),明显互相“转载”来“转载”去。可惜,转载的文章并不能真正解决问题。在这篇原创的文章中,我将自己摸索的经验分享了出来。下面转入正题。

循环导入的根本原因是什么?为什么会循环导入?
其实由循环导入,我们可以想到递归而引发的栈溢出。

def a(b):
   return a(b)

这,是一个明显错误的函数。一旦我们调用了函数,函数内部就会不加判断地再次调用此函数。而当我们加入了判断时:

def a(b):
if b == 1:
return 1
else:
return a(b - 1)

这样的话,该函数就转变为一个健康的函数了。

将同样的思路运用到相互导入的方式上。我们必须在整个文件初就要导入某个模块吗?一般来说不是的。我们应当将导入放在它真正被需要的函数里。比如,问题复现中的 a、b 改一下:

# mutualImportA.py  

a = 1  

def pA():  
from mutualImportB import b
   print(b)  

pA()
# mutualImportB.py  

b = 1  

def pB():  
from mutualImportA import a  
   print(a)  

pB()

这样的话,就没有上面的循环导入的问题了。这次再划分下流程:

Python相互导入的问题解决

OK,那么问题到此为止就解决完毕了。

当然,据此问题也衍生出了一些代码的规范问题:
开发中,若文件较小,还是最好不要将需要相互使用的两个函数或类分到两个文件中。这样,可以避免不少的问题。

来源:https://blog.csdn.net/meituwo/article/details/122322043

0
投稿

猜你喜欢

  •  在我们设计网页的时候,总会遇到一些不愉快的事情,最常见的莫过于在后台添加内容后才发现显示的页面被撑开,导致网页极度不美观。以前大
  • 三天前,你说下面的图是 PS 的,我信。而今天,这的的确确是张截图 -- 是的,这已经 不是梦想,是现实 -- 但实现梦想的不是微软,是 G
  • 目录1.列表2.使用格式3.一些很有用的函数4.元组 tuple5.元组的常用函数1.列表python没有数组,而是引入了列表(list),
  • PDOStatement::bindParamPDOStatement::bindParam — 绑定一个参数到指定的变量名(PHP 5 &
  •  AES(英文:Advanced Encryption Standard,中文:高级加密标准),是一种区块加密标准。AES将原始数
  • 技巧问题 Mysql的远程连接出现"Lost connection to MySQL server during query&qu
  • 本节为读者讲解如何利用ADO.NET本身的参数对象和存储过程技术防止注入攻击,以达到用户界面输入与原始SQL的分离,使黑客无法拼接SQL语句
  • oracle命令行删除用户: connect / as sysdba; shutdown abort; startup; drop user
  • 1.简介: java.util.regex是一个用正则表达式所订制的模式来对字符串进行匹配工作的类库包。 它包括两个类:Pattern和Ma
  • 本文实例总结了PHP中非常有用却鲜有人知的函数。分享给大家供大家参考,具体如下:PHP里有非常丰富的内置函数,很多我们都用过,但仍有很多的函
  • 主要要文件有:Index.html 实现功能,一个文本框,输入内容并实现提示 search.asp 查询功能,让文本框输入的内容在
  • 1、很多B2C或者淘宝的卖家反应,下单了但没有支付的占有率超过30%,有的甚至到40%。对于冲动性消费的商品来说,这个70%左右的转化率其实
  • 运行代码框<SCRIPT>var oPopup = window.createPopup();var popTop=50;fun
  • 如下所示:mystring.strip().replace(' ', '').replace('\n
  • 本文实例总结了php随机取mysql记录方法。分享给大家供大家参考。具体分析如下:在php中要随机取mysql记录我们可以直接使用mysql
  • 前段时间我通过观察韩国网站和其他作品发现了普遍存在黄金分割这样一个规律,不过只跟色相有关,明度、纯度还没做研究,今天看到论坛一篇“网页配色之
  • 就MySQL而言,大多数程序员都不太了解其设计背景,因此当他们尝试创建自己的数据库时,会留下很多漏洞。要想为MySQL数据库进行合适的配置,
  • 1、授权机制的主要作用是什么?授权机制的基本作用是给某个主机上的用户对某个数据库以select,insert,update和detete的权
  • 正在看的ORACLE教程是:Oracle数据库集复制方法浅议。前言 日益增长的分布式应用需求要求实现更好分布式的软件环境,不断推动着分布式技
  • 这几天忙个合作,开发iPhone版校友录。用了很久的iPhone,为它量身定制一套页面还是头一次,好在限制不是很多,会写html基本呈现就不
手机版 网络编程 asp之家 www.aspxhome.com