马上注册,结交更多好友,享用更多功能^_^
您需要 登录 才可以下载或查看,没有账号?立即注册
x
本帖最后由 天下有敌 于 2020-6-22 06:58 编辑
见第5题
原题:
5. 执行下边 a.py 或 b.py 任何一个文件,都会报错,请尝试解释一下此现象。# a.py
from b import y
def x():
print('x')
# b.py
from a import x
def y():
print('y')
会报找不到 函数错误。比如 执行a.x()会报 错误:ImportError: cannot import name 'x'
小甲鱼原话:这个是循环嵌套导入问题。无论运行 a.py 或 b.py 哪一个文件都会抛出 ImportError 异常。这是因为在执行其中某一个文件(a.py)的加载过程中,会创建模块对象并执行对应的字节码。但当执行第一个语句的时候需要导入另一个文件(from b import y),因此 CPU 会转而去加载另一个文件(b.py)。同理,执行另一个文件的第一个语句(from a import x)恰好也是需要导入之前的文件(a.py)。此时,之前的文件处于仅导入第一条语句的阶段,因此其对应的字典中并不存在 x,故抛出“ImportError: cannot import name 'x'”异常。
解决方案是直接使用 import 语句导入# a.py
import b
def x():
print('x')
# b.py
import a
def y():
print('y')
a.x()
我的问题: 感觉没有什么变化啊!就多了个a.x() 为什么用 import 就不会报错了?(我试了一下改成import方式导入也会报错。。。)找到原因了,我把a.x()放 b.py 文件里面了,这样不行。我就把 a.x() 从b.py文件去掉 在另一个文件调用就行了。
已经解决小甲鱼P51讲动手第一题参考答案已经详细说明了执行过程
原话:因为在执行 b.py 的加载过程中,需要创建新的模块对象 b,然后执行 b.py 对应的字节码。当遇到第一条语句(import a)的时候,Python 会转而去导入 a.py 并生成模块对象 a。同样遇到第一条语句(import b)的时候,Python 就跑去导入模块 b,此时发现 b 模块已经导入(在 sys.modules 中存在),继而执行 b 模块的字节码,当执行到 a.x() 的时候,由于模块 a 此时并未完全导入,所以抛出AttributeError 异常。 )}`,ewF
~lPQM=JZk.0tf:$5N9uC*H7AG"Wb
怕有些鱼油可能看不懂,小甲鱼给大家整理下,看 Python 是如何被当成猴子耍的:?rY&)ITWA
执行 b.py -> import a -> 查找 a 模块 -> 未发现 a 模块对象 -> 导入 a.py -> import b -> 查找 b 模块 -> 发现 b 模块对象 -> 接着往下执行字节码(import a 已执行过,Python 有机制确保不重复导入,因而不会再执行) -> a.x() -> 在 a 模块中找不到 x(),因为 a 还没有被完全导入嘛……jY'$tgql
Sfw8mBohE;tG4J,ZO*1'DQi@
好了,解决的方案也很简单,用这节课的知识,就是使用 if __name__ == "__main__" 来确保 Python 不要在导入的过程中调用不该调用的函数。
所以应该这么写:来# a.py
import b
def x():
print('x')
if __name__ == "__main__":
b.y()
# b.py
import a
def y():
print('y')
if __name__ == "__main__":
a.x()
|