【问题标题】:Python circular import when accessing method from class in separate module从单独模块中的类访问方法时的Python循环导入
【发布时间】:2021-05-07 18:15:52
【问题描述】:

我有两个模块,每个模块都包含一个类。在每个模块中,我想引用另一个模块中类的方法。我设置了一个小班来帮助我理解这个概念。我将一个模块导入另一个模块,但仍然收到循环导入错误。据我了解,这是正确的方法,但我仍然遇到错误。 这是我的示例类:

a.py 模块:

import b
class A():
    def __init__(self):
        print("A has run")
    def aa():
        print("aa has run")

b.B.bb()

b.py 模块:

import a
class B():
    def __init__(self):
        print("B has run")
    def bb():
        print("bb has run")
        # Run method from class in seperate module
        a.A.aa()

这是我的错误: AttributeError: partially initialized module 'b' has no attribute 'B' (most likely due to a circular import)

【问题讨论】:

  • 最简单的解决方案是将两个类放在同一个模块中。无论如何,a.A.aa()b.B.bb() 没有意义。你的方法不是方法。所以很可能,只需将这些函数作为模块级函数移动到它们自己的模块中

标签: python


【解决方案1】:

如果a.py 正在导入b.pyb.py 正在导入a.py,则这是循环导入。通常,您希望重组代码,以便您的模块不需要相互导入。如果不了解您的实际用例的更多信息,很难给出建议,但可能是这样的:

a.py 模块:

class A():
    def __init__(self):
        print("A has run")
    def aa():
        print("aa has run")

b.py 模块:

import a
class B():
    def __init__(self):
        print("B has run")
    def bb():
        print("bb has run")
        # Run method from class in seperate module
        a.A.aa()

c.py 模块

import b
b.B.bb()

【讨论】:

  • 所以我根本不能使用循环导入?我正在查看本指南以供参考,他们说如果您通过模块访问该类,则可以使用循环导入,例如本示例中的sbcode.net/python/proxy/#avoiding-circular-imports
  • 抱歉,我不太了解本指南中的内容。您正在查看的指南可能已过时。我只是想不出你会想要进行循环导入的任何现实场景
  • @TristanVerduzco 你可以,但你不应该
【解决方案2】:

您是对的,这是由于循环导入,原因是您的导入是在模块级别的,而不是如果您排除模块级别的导入,您将不会遇到问题,例如:

像这样修改你的代码:

class A():
    def __init__(self):
        print("A has run")
    def aa():
        print("aa has run")

if __name__ == '__main__':
    import b
    b.B.bb()

输出

bb has run
aa has run

现在,您将不再获得AttributeError,因为现在模块b 没有在模块a 的模块级别导入。

【讨论】:

    【解决方案3】:

    有点小技巧,但最简单(如果有技巧的话)摆脱这种情况的方法是

    class B():
        def __init__(self):
            print("B has run")
        def bb():
            print("bb has run")
            import a  # ?import on demand (each time)
    
    
            # Run method from class in seperate module
            a.A.aa()
    

    一个更好的方法是记住你的导入:

    import b
    class A():
        def __init__(self):
            print("A has run")
        def aa():
            print("aa has run")
    
    
    print("running A")
    b.B.bb()
    b.B.bb()
    
    
    class B():
        def __init__(self):
            print("B has run")
        def bb():
            print("bb has run")
            #remember your import of a
            a = getattr(B, "a", None)
            if not a:
                import a 
                B.a = a 
    
            # Run method from class in seperate module
            a.A.aa()
    
    

    您会注意到“运行 A”只发生了两次:一次是在您 python a.py 时,然后是第一次调用 b.B.bb() 并按需导入。

    【讨论】:

      猜你喜欢
      • 2020-12-25
      • 2012-10-13
      • 2016-08-05
      • 1970-01-01
      • 1970-01-01
      • 2020-07-23
      • 1970-01-01
      • 2019-12-04
      • 1970-01-01
      相关资源
      最近更新 更多