Python导入。再次...
我有这个文件结构:
[test]
start.py (from scripts import main)
[scripts]
__init__.py (empty)
main.py (from . import install)
install.py (from scripts import main # or # from . import main)
我收到导入错误:
vic@wic:~/projects/test$ python3 start.py
Traceback (most recent call last):
File "start.py", line 2, in <module>
from scripts import main
File "/home/vic/projects/test/scripts/main.py", line 1, in <module>
from . import install
File "/home/vic/projects/test/scripts/install.py", line 1, in <module>
from scripts import main
ImportError: cannot import name main
vic@wic:~/projects/test$
我不明白:第一次from scripts import main
工作(通过“工作”我的意思是它没有失败ImportError
),第二次相同的代码给出了ImportError: cannot import name main
< / p>
发生了什么事?
更新:
我的问题不是关于循环进口。令我感到困惑的是,第一次完全相同的代码from scripts import main
正常工作,然后第二次失败。
我猜有一些我不理解的内部导入机制。
第一次语句导入模块时,第二次完全相同的代码尝试从模块导入名称。这是如何工作的?
答案 0 :(得分:5)
您创建了一个循环导入。你不能这样做。避免从main
导入install
。
正在发生的事情是,导入的模块在执行整个顶级之前是不完整的。如果在执行期间它导入另一个(直接或间接)尝试再次导入原始模块的模块,则会失败。原始模块尚未完成导入。
换句话说,您正在创建一个圆形图:
start -> scripts.main -> scripts.install
^ |
| |
----------------
您需要重新安排代码,而无需从main
包中scripts
导入。
有关如何处理此问题的一些提示,请参阅What are the “best practices” for using import in a module?。
答案 1 :(得分:3)
main
导入install
和install
导入main
:
from scripts import main
start.py
导致
{li> from . import install
main.py
导致
{li> from scripts import main
install.py
- 循环导入
要解决循环导入,请将main
和install
合并到一个模块中,或者创建两个模块都可以导入的第三个模块。
答案 2 :(得分:0)
这应该有效:
start.py:
from scripts import main
脚本/ main.py:
import install
脚本/ install.py:
import main
答案 3 :(得分:0)
这是我用来覆盖默认行为的补丁:
import sys
import builtins
import importlib
def _import(name, globals=None, locals=None, fromlist=None, level=0, __import__=__import__):
"""A hack to to make names of imported modules to be available in the parent package before
they are fully imported. If a module is present in sys.modules event if it's not fully
imported, it should not be a problem.
I.e. ``from package import module1, module2`` will create variables ``package.module1`` and
``package.module2`` at start of the import, not when it's finished.
This helps in some situations with circular import.
"""
module = __import__(name, globals, locals, fromlist, level)
for attr in fromlist or ():
sub_module = sys.modules.get(module.__name__ + '.' + attr)
if sub_module: # is this a module?
# if subpackage is already being imported, even if not finished,
# inject its name into the parent package
setattr(module, attr, sub_module)
return module
builtins.__import__ = _import
这是一个测试它的项目:https://github.com/warvariuc/python_import_improver