war*_*iuc 12 python importerror python-3.x
Python导入让我发疯(我在某些时候使用python导入的经验根本不符合'明确比隐含更好':():
[app]
start.py
from package1 import module1
[package1]
__init__.py
print('Init package1')
module1.py
print('Init package1.module1')
from . import module2
module2.py
print('Init package1.module2')
import sys, pprint
pprint.pprint(sys.modules)
from . import module1
Run Code Online (Sandbox Code Playgroud)
我明白了:
vic@ubuntu:~/Desktop/app2$ python3 start.py
Init package1
Init package1.module1
Init package1.module2
{'__main__': <module '__main__' from 'start.py'>,
...
'package1': <module 'package1' from '/home/vic/Desktop/app2/package1/__init__.py'>,
'package1.module1': <module 'package1.module1' from '/home/vic/Desktop/app2/package1/module1.py'>,
'package1.module2': <module 'package1.module2' from '/home/vic/Desktop/app2/package1/module2.py'>,
...
Traceback (most recent call last):
File "start.py", line 3, in <module>
from package1 import module1
File "/home/vic/Desktop/app2/package1/module1.py", line 3, in <module>
from . import module2
File "/home/vic/Desktop/app2/package1/module2.py", line 5, in <module>
from . import module1
ImportError: cannot import name module1
vic@ubuntu:~/Desktop/app2$
Run Code Online (Sandbox Code Playgroud)
import package1.module1工作,但我想使用,from . import module1因为我想package1为我的其他应用程序使便携式,这就是为什么我想使用相对路径.
我正在使用python 3.
我需要循环进口.module1中的函数声明其参数之一是module2中定义的类的实例,反之亦然.
换一种说法:
sys.modules包含'package1.module1': <module 'package1.module1' from '/home/vic/Desktop/app2/package1/module1.py'>.我希望在表单中获得对它的引用from . import module1,但它试图得到一个名称,而不是像大小写的包import package1.module1(它工作正常).我试过import .module1 as m1- 但这是一个语法错误.
此外,from . import module2在module1工作正常,但from . import module1在module2工作中...
更新:
这个黑客有效(但我正在寻找'官方'方式):
print('Init package1.module2')
import sys, pprint
pprint.pprint(sys.modules)
#from . import module1
parent_module_name = __name__.rpartition('.')[0]
module1 = sys.modules[parent_module_name + '.module1']
Run Code Online (Sandbox Code Playgroud)
通常应该避免循环导入,参见相关问题的这个答案,或者关于effbot.org的这篇文章.
在这种情况下,问题是,你导入from .其中,.是当前包.所以你的所有from . import X进口都要通过包装__init__.py.
如果您明确地导入模块__init__.py并给它们另一个名称(并调整其他导入以使用这些名称),您可以使问题更加明显:
print('Init package1')
from . import module1 as m1
from . import module2 as m2
Run Code Online (Sandbox Code Playgroud)
现在,当您导入m1时start.py,包首先初始化m1并进入该from . import m2行.此时,没有m2已知的,__init__.py因此您会收到导入错误.如果你在__init__.py周围切换import语句(所以你m2先加载),然后在m2其中找到该from . import m1行,由于与以前相同的原因失败.
如果你没有明确地导入__init__.py类似的东西仍然在后台发生.不同之处在于您获得的结构较不扁平(因为导入不再仅从包中启动).这样既module1和module2得到"开始",你会得到相应的初始化打印.
为了使它工作,你可以进行绝对导入module2.这样你就可以避免包首先解决所有问题,并使其重用导入start.py(因为它具有相同的导入路径).
或者甚至更好,你完全摆脱了循环导入.如果您有循环引用,通常表明您的应用程序结构不太好.
(我希望我的解释没有任何意义,我已经很难写了,但总的想法应该是明确的,我希望...)
响应您的更新; 您正在做的是使用完整的包名来获取对模块的引用.这与使其工作的第一个可能选项等效(但要复杂得多); 您使用与中的相同导入路径使用绝对导入start.py.