工作遇到了一个引用循环的问题,记录一下
test.py:
print('fffffff')
import main # 导入 main.py
print('sdfdf')
def aaa():
print('aaaaaaaaaaa')
main.py:
print('-------------')
from test import aaa # 试图从 test.py 导入 aaa 函数
print('xxxxxxxxxxxxxxxxx')
tttt.py:
import test # 导入 test.py
这里出现了一个循环导入的问题,即test.py导入了main.py,而main.py又试图从test.py导入内容。循环导入一般情况下会导致问题,尤其是当涉及到模块级别的代码执行时。
当直接运行tttt.py时,以下是发生的事情:
- tttt.py 导入 test.py。
- test.py 开始执行,首先打印 'fffffff'。
- test.py 尝试导入 main.py。
- main.py 开始执行,首先打印 '-------------'。
- main.py 尝试从 test.py 导入 aaa 函数。
此时,test.py 已经在执行中,但还没有完全执行完毕,因为它被 main.py 的导入操作暂停了。因此,test.py 中定义的 aaa 函数对 main.py 来说还不可见。
这导致 main.py 不能从 test.py 导入 aaa 函数,因此产生循环导入错误。
直接运行test.py时,以下是发生的事情:
- test.py 执行,打印 'fffffff'。
- test.py 导入 main.py。
- main.py 执行,打印 '-------------'。
- main.py 尝试从 test.py 导入 aaa 函数,但此时不会产生错误,因为 test.py 已经开始执行了,并且定义了 aaa 函数。所以,导入成功。
- main.py 继续执行,打印 'xxxxxxxxxxxxxxxxx'。
- test.py 继续执行,打印 'sdfdf'。
直接执行main.py会产生错误,是因为:
- main.py 执行,打印 '-------------'。
- main.py 尝试从 test.py 导入 aaa 函数。
- test.py 开始执行,打印 'fffffff'。
- test.py 尝试导入 main.py,但 main.py 已经在执行堆栈中了,因此不会再次执行其代码。
由于 test.py 中 aaa 函数的定义在导入 main.py 的语句之后,所以 main.py 还看不到它,导致导入失败,产生错误。
循环导入问题通常可以通过重新组织代码结构来解决,比如将共享的函数或类移到一个单独的模块中,或者将导入语句移到函数内部或程序的最后,以避免在模块级别就发生导入。此外,使用延迟导入(即在需要时才进行导入)也是一种解决方法。
当 Python 导入一个模块时,它实际上执行了该模块中的所有顶级代码。导入模块的时候,Python 会创建一个新的命名空间,并在这个命名空间内执行模块的代码。当模块中的代码执行完毕后,其结果(包括定义的变量、函数、类等)都存储在此命名空间中,并且可以被其他代码访问。
Python 在执行模块时会先将模块名添加到 sys.modules 中,标记为正在导入。如果在这个过程中遇到了循环引用,但所有涉及到的函数和类等都已经定义好,那么 Python 就可以正常处理这个导入,不会抛出错误。但如果在执行到循环引用的地方,相关函数或变量还未定义,就会导致导入失败。
在例子中,当 main.py 试图从 test.py 导入 aaa 时,Python 查看 sys.modules,发现 test.py 已经在模块列表中,所以不会再次初始化 test.py,只是继续执行它。至此,aaa 尚未定义,但是在 main.py 导入 aaa 之后,test.py 中剩余的代码会继续执行,此时 aaa 函数得以定义。这就是为什么当直接执行 test.py 时不会产生错误的原因。
其实循环引用主要是因为代码结构没设计好才出现的,在循环引用出现了之后最好是应该把结构改改,而不是在原基础上修
PS:chatgpt真好用~
标签:aaa,函数,python,py,导入,循环,引用,test,main From: https://www.cnblogs.com/xxxxxxxxjh/p/17925668.html