Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/322.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在python包内导入_Python - Fatal编程技术网

在python包内导入

在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

我在以下代码中遇到导入错误(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 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中导入模块可以吗

  • 我的分析是:

    根据阅读资料,我认识到最大的问题可能是,因为

    __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
    
  • 正确的方法是具有跨模块依赖关系,而不是循环依赖关系。您应该确定项目的层次结构,并将依赖关系图安排在DAG(有向无环图)中

  • 您在包
    \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
    而不是