在python包内导入
我在以下代码中遇到导入错误(ImportError:无法导入名称“ClassB”): 目录结构:在python包内导入,python,Python,我在以下代码中遇到导入错误(ImportError:无法导入名称“ClassB”): 目录结构: main.py test_pkg/ __init__.py a.py b.py main.py: from test_pkg import ClassA, ClassB from .a import ClassA from .b import ClassB from test_pkg import ClassB class ClassA: pass class
main.py
test_pkg/
__init__.py
a.py
b.py
main.py
:
from test_pkg import ClassA, ClassB
from .a import ClassA
from .b import ClassB
from test_pkg import ClassB
class ClassA:
pass
class ClassB:
pass
from test_pkg import A, B
class B:
pass
from .b import B
class A:
pass
from .a import A
from .b import B
from test_pkg import A, B
\uuuu init\uuuuu.py
:
from test_pkg import ClassA, ClassB
from .a import ClassA
from .b import ClassB
from test_pkg import ClassB
class ClassA:
pass
class ClassB:
pass
from test_pkg import A, B
class B:
pass
from .b import B
class A:
pass
from .a import A
from .b import B
from test_pkg import A, B
a.py
:
from test_pkg import ClassA, ClassB
from .a import ClassA
from .b import ClassB
from test_pkg import ClassB
class ClassA:
pass
class ClassB:
pass
from test_pkg import A, B
class B:
pass
from .b import B
class A:
pass
from .a import A
from .b import B
from test_pkg import A, B
b.py
:
from test_pkg import ClassA, ClassB
from .a import ClassA
from .b import ClassB
from test_pkg import ClassB
class ClassA:
pass
class ClassB:
pass
from test_pkg import A, B
class B:
pass
from .b import B
class A:
pass
from .a import A
from .b import B
from test_pkg import A, B
过去,我通过在a.py的import中添加全名,通过快速“实验”修复了它:
from test_pkg.b import ClassB
class ClassA:
pass
a.py:
from test_pkg import ClassB
class ClassA:
pass
我已阅读了有关进口机械的信息,并根据:
该名称将在导入搜索的各个阶段使用,它可能是子模块的虚线路径,例如foo.bar.baz。在本例中,Python首先尝试导入foo,然后是foo.bar,最后是foo.bar.baz
我原以为它会再次失败,因为它会在test_pkg导入期间尝试导入test_pkg,但它正在工作。我的问题是为什么
另外还有2个问题:
我的分析是: 根据阅读资料,我认识到最大的问题可能是,因为
__init__.py:
from .a import ClassA
from .b import ClassB
ClassA和ClassB导入作为test_pkg导入的一部分执行,但随后在a.py中点击import语句:
from test_pkg.b import ClassB
class ClassA:
pass
a.py:
from test_pkg import ClassB
class ClassA:
pass
它失败是因为发生了循环依赖关系
但在使用以下命令导入时,该命令起作用:
from test_pkg.b import ClassB
根据我的理解,不应该这样,因为:
此名称将用于导入搜索的各个阶段,并且
可以是子模块的点路径,例如foo.bar.baz。在这种情况下,,
Python首先尝试导入foo,然后是foo.bar,最后是
foo.bar.baz。如果任何中间导入失败,则
引发ModuleNotFoundError
所以我期望两个导入的行为相同
看起来完整路径导入未启动有问题的测试\u pkg导入进程
from test_pkg.b import ClassB
我希望编写的代码可能是:
main.py
:
from test_pkg import ClassA, ClassB
from .a import ClassA
from .b import ClassB
from test_pkg import ClassB
class ClassA:
pass
class ClassB:
pass
from test_pkg import A, B
class B:
pass
from .b import B
class A:
pass
from .a import A
from .b import B
from test_pkg import A, B
b.py
:
from test_pkg import ClassA, ClassB
from .a import ClassA
from .b import ClassB
from test_pkg import ClassB
class ClassA:
pass
class ClassB:
pass
from test_pkg import A, B
class B:
pass
from .b import B
class A:
pass
from .a import A
from .b import B
from test_pkg import A, B
a.py
:
from test_pkg import ClassA, ClassB
from .a import ClassA
from .b import ClassB
from test_pkg import ClassB
class ClassA:
pass
class ClassB:
pass
from test_pkg import A, B
class B:
pass
from .b import B
class A:
pass
from .a import A
from .b import B
from test_pkg import A, B
\uuuu init\uuuuu.py
:
from test_pkg import ClassA, ClassB
from .a import ClassA
from .b import ClassB
from test_pkg import ClassB
class ClassA:
pass
class ClassB:
pass
from test_pkg import A, B
class B:
pass
from .b import B
class A:
pass
from .a import A
from .b import B
from test_pkg import A, B
main.py
:
from test_pkg import ClassA, ClassB
from .a import ClassA
from .b import ClassB
from test_pkg import ClassB
class ClassA:
pass
class ClassB:
pass
from test_pkg import A, B
class B:
pass
from .b import B
class A:
pass
from .a import A
from .b import B
from test_pkg import A, B
\uuuu init\uuuu.py
中放入的内容将是您可以通过包访问的内容。此外,您还可以在\uuuuu init\uuuuuuuuuupy
中使用\uuuuuuu all\uuuuuuuuuuuuuuuuuuuuuuuuuu
参考此文件您的文件名为
b.py
,但您正在尝试导入b
,而不是导入b
根据您的平台(有关详细信息,请参阅),这可能有效,也可能无效。如果不起作用,症状将与您看到的完全相同:ImportError:无法导入名称“B”
修复方法是从test\u okg import b。或者,如果希望将模块命名为B
,请将文件重命名为B.py
这实际上与包无关(除了您收到的错误消息说,无法导入名称“B”
,而不是没有名为“B”的模块
,因为在失败的from…import
语句中,Python无法判断您是未能从包导入模块,还是未能从模块导入某个全局名称)
那么,为什么会这样呢
from test_pkg.b import B
我原以为它会再次失败,因为它会在test_pkg导入期间尝试导入test_pkg,但它正在工作。我的问题是为什么
因为导入test\u pkg
一开始就不是问题;正在导入测试包B。您通过导入test_pkg.b
解决了这个问题
在test\u pkg/b.py
中成功找到了test\u pkg.b
然后,test\u pkg.b.b
在该模块中找到,并导入到您的模块中,因为b.py
中当然有一个class b:
语句
关于您的后续问题:
采用跨模块依赖关系是否合适
跨模块依赖关系没有问题,只要它们不是循环的,而您的不是循环的
对于test\u pkg.a
来说,使用绝对导入导入test\u pkg.b
是非常好的,就像从test\u pkg import b导入一样
但是,通常最好使用相对导入,如from。导入b
(除非您需要在Python2.x和3.x上工作相同的双版本代码)。解释为什么相对导入通常更适合于包内依赖项(以及为什么它只是“通常”而不是“始终”)
在包中导入模块可以吗
对。事实上,这是一个非常常见的习语,有多种用途
例如,请参见,它从其每个子模块导入所有公共导出并重新导出它们。子模块中有一些很少使用的名称,它们不是以\uuu
开头,但不包括在\uuuu all\uu
中,如果要使用这些名称,则需要显式导入子模块。但是在一个典型的程序中你可能需要的所有东西都包含在\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu>中,并由包重新导出,所以你可以只编写,例如asyncio.Lock
而不是