如何使用Python循环导入 3
How to circular import using Python 3
我想出了一个简单的代码,我无法弄清楚为什么以及如何通过循环导入解决它。
test.py
from test2 import specific_ID
store_name = "testing"
STORE_ID = specific_ID()
print(STORE_ID)
test2.py
from test import store_name
print(store_name)
def specific_ID():
print("Yay works")
print(f"Store name: {store_name}")
return True
我的想法是,当我在 test.py
中有变量 store_name
时,我希望它是一种“常量”值,我可以在其中重新使用 [=] 中的值16=] - 但是它似乎不喜欢它抛出错误的地方:
from test2 import specific_ID
ImportError: cannot import name 'specific_ID' from partially initialized module 'test2' (most likely due to a circular import)
我的问题是,如何重新使用从 test.py 到 test.py 的变量?
应避免循环导入,只需将 test.py 和 test2.py 放在一个包中,并将它们的共享全局变量放在主命名空间中:
__init__.py
STORE_NAME = 'testing'
test.py 和 test2.py
from . import STORE_NAME
但是你可以一起规避全局变量:
test2.py
def specific_ID(store_name: str) -> int:
"Return the ID for a store"
print("Yay works")
print(f"Store name: {store_name}")
# lookup id
return id
test.py
from test2 import specific_ID
store_name = "testing"
STORE_ID = specific_ID(store_name)
print(STORE_ID)
当你的函数是纯函数,与全局状态分开时,这使得它们更容易推理和重构。
TLDR:因为在 test2.py 中你只需要引用 store_name 变量,删除 specific_id 的导入和引用 specific_id 的代码,错误应该走开。
长答案:test.py 中的循环导入错误由以下行引起:
from test2 import specific_ID
当python遇到这一行时,它会暂停test.py的执行,并尝试处理test2.py,这样它就可以得到正在执行的项的值已导入,在本例中为 specific_id 函数。
然而,当我们仔细查看 test2.py 时,我们可以看到在文件的顶部,它正试图从 test.py:
导入
from test import store_name
现在,由于我们通过 Python 在 test.py 上暂停执行达到了这一点,这意味着变量 store_name
根本没有被 Python 处理过,因此 test2.py 无法从 test.py 导入它,从而导致循环导入错误。在我看来,文件最好看起来像这样以消除错误:
test.py:
store_name = "testing"
test2.py:
from test import store_name
print(store_name)
def specific_ID():
print("Yay works")
print(f"Store name: {store_name}")
return True
STORE_ID = specific_ID()
print(STORE_ID)
其他两个答案提供了关于如何构建代码以及为什么会出现错误的很好的建议。你应该听他们的,因为他们告诉你做事的正确方法。这个答案与此无关。相反,让我们找出可以使导入真正起作用的最小更改集。
V1
只要 test
定义了 store_name
,test2
就会正常导入。您可以通过将 test
中的导入向下移动一行来确保发生这种情况:
store_name = "testing"
from test2 import specific_ID
STORE_ID = specific_ID()
print(STORE_ID)
V2
反之亦然:只要 test2
定义了 specific_ID
,test
的导入就可以正常工作。两项更改将允许这样做。一种是在函数定义之后移动导入,因为函数中使用的名称不需要存在,直到你 运行 it:
def specific_ID():
print("Yay works")
print(f"Store name: {store_name}")
return True
from test import store_name
print(store_name)
将导入放在末尾是处理循环导入的“常用”技术。 Common 在引号中,因为问题实际上并不那么普遍,而且一开始就是代码味道。你不应该一开始就这样修复它。
V2b
test2
的第二个选项是在函数内部执行导入。这是一个更重要的变化,因为您还必须去掉 print 语句。考虑到导入的工作方式,除了创建对已加载模块的本地引用之外,导入语句实际上不会做任何事情,因此您不必在每次 运行 函数时都担心昂贵的操作:
def specific_ID():
from test import store_name
print("Yay works")
print(f"Store name: {store_name}")
return True
我想出了一个简单的代码,我无法弄清楚为什么以及如何通过循环导入解决它。
test.py
from test2 import specific_ID
store_name = "testing"
STORE_ID = specific_ID()
print(STORE_ID)
test2.py
from test import store_name
print(store_name)
def specific_ID():
print("Yay works")
print(f"Store name: {store_name}")
return True
我的想法是,当我在 test.py
中有变量 store_name
时,我希望它是一种“常量”值,我可以在其中重新使用 [=] 中的值16=] - 但是它似乎不喜欢它抛出错误的地方:
from test2 import specific_ID
ImportError: cannot import name 'specific_ID' from partially initialized module 'test2' (most likely due to a circular import)
我的问题是,如何重新使用从 test.py 到 test.py 的变量?
应避免循环导入,只需将 test.py 和 test2.py 放在一个包中,并将它们的共享全局变量放在主命名空间中:
__init__.py
STORE_NAME = 'testing'
test.py 和 test2.py
from . import STORE_NAME
但是你可以一起规避全局变量:
test2.py
def specific_ID(store_name: str) -> int:
"Return the ID for a store"
print("Yay works")
print(f"Store name: {store_name}")
# lookup id
return id
test.py
from test2 import specific_ID
store_name = "testing"
STORE_ID = specific_ID(store_name)
print(STORE_ID)
当你的函数是纯函数,与全局状态分开时,这使得它们更容易推理和重构。
TLDR:因为在 test2.py 中你只需要引用 store_name 变量,删除 specific_id 的导入和引用 specific_id 的代码,错误应该走开。
长答案:test.py 中的循环导入错误由以下行引起:
from test2 import specific_ID
当python遇到这一行时,它会暂停test.py的执行,并尝试处理test2.py,这样它就可以得到正在执行的项的值已导入,在本例中为 specific_id 函数。
然而,当我们仔细查看 test2.py 时,我们可以看到在文件的顶部,它正试图从 test.py:
导入from test import store_name
现在,由于我们通过 Python 在 test.py 上暂停执行达到了这一点,这意味着变量 store_name
根本没有被 Python 处理过,因此 test2.py 无法从 test.py 导入它,从而导致循环导入错误。在我看来,文件最好看起来像这样以消除错误:
test.py:
store_name = "testing"
test2.py:
from test import store_name
print(store_name)
def specific_ID():
print("Yay works")
print(f"Store name: {store_name}")
return True
STORE_ID = specific_ID()
print(STORE_ID)
其他两个答案提供了关于如何构建代码以及为什么会出现错误的很好的建议。你应该听他们的,因为他们告诉你做事的正确方法。这个答案与此无关。相反,让我们找出可以使导入真正起作用的最小更改集。
V1
只要test
定义了 store_name
,test2
就会正常导入。您可以通过将 test
中的导入向下移动一行来确保发生这种情况:
store_name = "testing"
from test2 import specific_ID
STORE_ID = specific_ID()
print(STORE_ID)
V2
反之亦然:只要 test2
定义了 specific_ID
,test
的导入就可以正常工作。两项更改将允许这样做。一种是在函数定义之后移动导入,因为函数中使用的名称不需要存在,直到你 运行 it:
def specific_ID():
print("Yay works")
print(f"Store name: {store_name}")
return True
from test import store_name
print(store_name)
将导入放在末尾是处理循环导入的“常用”技术。 Common 在引号中,因为问题实际上并不那么普遍,而且一开始就是代码味道。你不应该一开始就这样修复它。
V2b
test2
的第二个选项是在函数内部执行导入。这是一个更重要的变化,因为您还必须去掉 print 语句。考虑到导入的工作方式,除了创建对已加载模块的本地引用之外,导入语句实际上不会做任何事情,因此您不必在每次 运行 函数时都担心昂贵的操作:
def specific_ID():
from test import store_name
print("Yay works")
print(f"Store name: {store_name}")
return True