【ModuleNotFoundError 与 ImportError】之 most likely due to a circular import

本文详细介绍了Python中ModuleNotFoundError和ImportError的常见原因,特别是由于循环导入导致的错误。通过实例分析了解解释器的操作步骤,提出了解决此类问题的三种方法,包括将代码放入函数、调整导入顺序和重构代码。Guido van Rossum的建议是避免from...import...,使用模块名.变量名的方式,并限制全局变量初始化。


前言

提示:这里可以添加本文要记录的大概内容:

“most likely due to a circular import”翻译为“很可能是由于循环导入”,提示 ImportError,在对自定义模块的引用中出现。Python 学习手册《编程常见问题》对“How can I have modules that mutually import each other?”的回答解决了这个问题。本文是对这一内容的抄录和整理。


提示:以下是本篇文章正文内容,下面案例可供参考

1 示例

如下示例来自学习手册:

在这里插入图片描述

2 解释器的操作步骤

在这里插入图片描述

3 错误分析

对上述操作步骤的错误分析:

  1. The last step fails, because Python isn’t done with interpreting foo yet and the global symbol dictionary for foo is still empty.
    最后一步失败了,因为 Python 还没有完成对 foo 的解释,而且 foo 的全局符号字典仍然是空的。
  2. The same thing happens when you use import foo, and then try to access foo.foo_var in global code.
    当您使用 import foo,然后尝试在全局代码中访问 foo.foo_var 时,也会发生同样的事情。

4 解决办法

这个问题有(至少)三种可能的解决方法。

  1. Guido van Rossum recommends avoiding all uses of from import …, and placing all code inside functions. Initializations of global variables and class variables should use constants or built-in functions only. This means everything from an imported module is referenced as < module >.< name >.
    Guido van Rossum 建议避免使用 from < module > import …,并将所有代码放在函数中。 全局变量和类变量的初始化应该只使用常量或内置函数。 这意味着导入模块中的所有内容都被引用为 < module >.< name >。
  2. Jim Roskind suggests performing steps in the following order in each module:
    建议在每个模块中按以下顺序执行:
  • exports (globals, functions, and classes that don’t need imported base classes)
    导出(不需要导入基类的全局变量、函数和类)
  • import statements
    import 语句
  • active code (including globals that are initialized from imported values).
    活动代码(包括从导入值初始化的全局变量)。
    Guido van Rossum doesn’t like this approach much because the imports appear in a strange place, but it does work.
    Guido van Rossum 不太喜欢这种方法,因为导入出现在一个陌生的地方,但它确实有效。
  1. Matthias Urlichs recommends restructuring your code so that the recursive import is not necessary in the first place.
    Matthias Urlichs 建议重新构建您的代码,以便一开始就不需要递归导入。

这些解决方案并不相互排斥。


5 运行示例

体会一下循环导入的运行实例:
在这里插入图片描述


总结

  1. 我个人推荐 Guido van Rossum 的建议:
    1.1. 避免使用 from < module > import …,并将所有代码放在函数中。
    1.2. 全局变量和类变量的初始化应该只使用常量或内置函数。
    1.3. 这意味着导入模块中的所有内容都被引用为 < module >.< name >。
  2. 我的老师尹成有一个串联类的示例里,直接用 self 变量解决了,也值得学习!
    2.1. 实际上避免了创建两个实例的问题。
    在这里插入图片描述


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值