导入不工作
Import not Working
我有两个文件 a.py
和 b.py
。
在 a.py 中,
我们
import xxx
from b import *
在 b.py 中我们有一个需要 module xxx
的函数。
现在,当从 a.py
调用 b.py
中的函数时,它找不到模块 xxx
.
为什么会这样?解决方法是什么?
由于某些原因,我无法在 b.py
中执行 import xxx
。
MCV:
a.py
import xxx
from b import *
fun()
b.py
def fun():
xxx.dosomething()
错误:
Global name xxx not defined
问题:
a.py:
import numpy
print("a.py is imported")
b.py:
import a
numpy.zeros(8)
结果(python3 b.py):
a.py is imported
Traceback (most recent call last):
File "b.py", line 3, in <module>
numpy.zeros(8)
NameError: name 'numpy' is not defined
答案:
我想这更适合编写库。假设a.py是库的一部分,b是使用库的用户程序,库是我写的。如果我在 a.py 中导入的所有内容 (import numpy
) 都显示在 b.py 中,我的库的 API 将不会那么干净,因为我无法隐藏 numpy 库来自我图书馆的用户。我想这就是如果 b.py 导入 a.py.
,那么 a.py 中导入的库从 b.py 中隐藏的原因
您可以在 b.py
中导入 xxx
如果其名称与您在 b 中导入的另一个文件冲突,请执行以下操作:
import xxx as some_name
并且在 b.py 中,您现在可以将其称为 some_name,即
some_name.run()
这是一组试图模拟您的问题的两个文件。版本 1 是您所描述的,版本 2 是有效的。
版本 1(OP 问题)
文件'a.py':
print("a.py: entered a.py")
import math
print("a.py: imported math")
print("a.py: 1st dir()={}".format(dir()))
from b import *
print("a.py: imported * from b")
print("a.py: 2nd dir()={}".format(dir()))
def angle(x, y):
return math.acos(x/mysq(x*x+y*y))
print("a.py: angle has been defined")
print("a.py: 3rd dir()={}".format(dir()))
import b
print("a.py: dir(b)={}".format(dir(b)))
文件'b.py':
print("b.py: entered b.py")
print("b.py: 1st dir():{}".format(dir()))
def mysq(x):
return math.sqrt(x)
print("b.py: mysq has been defined")
print("b.py: 2nd dir():{}".format(dir()))
print("b.py: leaving b.py...")
然后
>>> import a
a.py: entered a.py
a.py: imported math
a.py: 1st dir()=['__builtins__', '__cached__', '__doc__', '__file__',
'__loader__', '__name__', '__package__', '__spec__',
'math']
b.py: entered b.py
b.py: 1st dir():['__builtins__', '__cached__', '__doc__', '__file__',
'__loader__', '__name__', '__package__', '__spec__']
b.py: mysq has been defined
b.py: 2nd dir():['__builtins__', '__cached__', '__doc__', '__file__',
'__loader__', '__name__', '__package__', '__spec__',
'mysq'] # <-- NOTICE that module 'b' is still hasn't
# loaded 'math' before leaving it!!!
b.py: leaving b.py...
a.py: imported * from b
a.py: 2nd dir()=['__builtins__', '__cached__', '__doc__', '__file__',
'__loader__', '__name__', '__package__', '__spec__',
'math', 'mysq']
a.py: angle has been defined
a.py: 3rd dir()=['__builtins__', '__cached__', '__doc__', '__file__',
'__loader__', '__name__', '__package__', '__spec__',
'angle', 'math', 'mysq']
a.py: dir(b)=['__builtins__', '__cached__', '__doc__', '__file__',
'__loader__', '__name__', '__package__', '__spec__',
'mysq'] # <-- NOTICE that module 'b' is still not aware of 'math'!!!
>>> a.angle(7,8)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/Users/.../a.py", line 9, in angle
return math.acos(x/mysq(x*x+y*y))
File "/Users/.../b.py", line 4, in mysq
return math.sqrt(x)
NameError: name 'math' is not defined
版本 2(工作)
将 import math
放入 b.py
并将其从 a.py
中删除:
文件'a.py':
from b import *
print("a.py: imported * from b")
print("a.py: 1st dir()={}".format(dir()))
def angle(x, y):
return math.acos(x/mysq(x*x+y*y))
print("a.py: angle has been defined")
print("a.py: 2nd dir()={}".format(dir()))
文件'b.py':
print("b.py: entered b.py")
import math
print("b.py: loaded math")
print("b.py: 1st dir():{}".format(dir()))
def mysq(x):
return math.sqrt(x)
print("b.py: mysq has been defined")
print("b.py: 2nd dir():{}".format(dir()))
print("b.py: leaving b.py...")
然后
>>> import a
b.py: entered b.py
b.py: loaded math
b.py: 1st dir():['__builtins__', '__cached__', '__doc__', '__file__',
'__loader__', '__name__', '__package__', '__spec__', 'math']
b.py: mysq has been defined
b.py: 2nd dir():['__builtins__', '__cached__', '__doc__', '__file__',
'__loader__', '__name__', '__package__', '__spec__',
'math', 'mysq']
b.py: leaving b.py...
a.py: imported * from b
a.py: 1st dir()=['__builtins__', '__cached__', '__doc__', '__file__',
'__loader__', '__name__', '__package__', '__spec__',
'math', 'mysq'] # <-- NOTICE 'math' in a.py!!!
a.py: angle has been defined
a.py: 2nd dir()=['__builtins__', '__cached__', '__doc__', '__file__',
'__loader__', '__name__', '__package__', '__spec__',
'angle', 'math', 'mysq']
>>> a.angle(7,8)
0.8519663271732721
我无法准确解释(表述)这种行为背后的机制,但对我来说似乎是合理的:b.py
中的 mysq()
应该如何了解 math
?大量 print
语句的输出表明,在版本 1(OP 问题)中,从 b
导入会导致将 a.py
中 defined/imported 在 [=23] 中的所有内容导入到 a.py
的命名空间中=].整个 b.py
在导入 a.py
时执行一次。但是,b
本身从来没有 "knows" 关于 math
.
的任何事情
在版本 2 中,一切都按预期工作,因为 math
被导入 b
,它在导入 a
时立即执行,并从 [=29= 导入所有内容](包括math
)变成a
.
现在,让我们再做一些实验...让我们破解版本 2:
版本 2b(损坏)
在此版本中,我们将 a.py
修改如下(b.py
与版本 2 相同):
文件'a.py':
import b # <-- We do not import 'math' from b into a!
# Is it still "loaded" somehow into 'a'?
def angle(x, y):
return math.acos(x/b.mysq(x*x+y*y))
导入 "just" b
本身(与从 b
导入所有内容 相反)不会将 math
导入 a
:
>>> a.angle(7,8)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/Users/.../a.py", line 10, in angle
return math.acos(x/b.mysq(x*x+y*y))
NameError: name 'math' is not defined
版本 1b(固定)
最后,让我们通过将 a
中的所有内容导入 b
以及继续将 b
中的所有内容导入 a
来修复版本 1:
文件'a.py':
print("a.py: entered a.py")
import math
print("a.py: imported math")
print("a.py: 1st dir()={}".format(dir()))
from b import *
print("a.py: imported * from b")
print("a.py: 2nd dir()={}".format(dir()))
def angle(x, y):
return math.acos(x/mysq(x*x+y*y))
print("a.py: angle has been defined")
print("a.py: 3rd dir()={}".format(dir()))
import b # extra check of b
print("a.py: dir(b)={}".format(dir(b)))
文件'b.py':
print("b.py: entered b.py")
print("b.py: 1st dir():{}".format(dir()))
from a import *
print("b.py: imported * from a")
print("b.py: 2nd dir():{}".format(dir()))
def mysq(x):
return math.sqrt(x)
print("b.py: mysq has been defined")
print("b.py: 3rd dir():{}".format(dir()))
print("b.py: leaving b.py...")
然后
>>> import a
a.py: entered a.py
a.py: imported math
a.py: 1st dir()=['__builtins__', '__cached__', '__doc__', '__file__',
'__loader__', '__name__', '__package__', '__spec__',
'math'] # 'math' is loaded first into 'a'
b.py: entered b.py
b.py: 1st dir():['__builtins__', '__cached__', '__doc__', '__file__',
'__loader__', '__name__', '__package__', '__spec__'
] # 'b' doesn't "know" yet about 'math'
b.py: imported * from a
b.py: 2nd dir():['__builtins__', '__cached__', '__doc__', '__file__',
'__loader__', '__name__', '__package__', '__spec__',
'math'] # after importing *(!!!) from 'a' into 'b', 'b' now has 'math'
b.py: mysq has been defined
b.py: 3rd dir():['__builtins__', '__cached__', '__doc__', '__file__',
'__loader__', '__name__', '__package__', '__spec__',
'math', 'mysq']
b.py: leaving b.py...
a.py: imported * from b
a.py: 2nd dir()=['__builtins__', '__cached__', '__doc__', '__file__',
'__loader__', '__name__', '__package__', '__spec__',
'math', 'mysq'] # NOTICE: math is not imported twice into 'a'
a.py: angle has been defined
a.py: 3rd dir()=['__builtins__', '__cached__', '__doc__', '__file__',
'__loader__', '__name__', '__package__', '__spec__',
'angle', 'math', 'mysq']
a.py: dir(b)=['__builtins__', '__cached__', '__doc__', '__file__',
'__loader__', '__name__', '__package__', '__spec__',
'math', 'mysq'] # just to make sure, check that 'b' still has 'math' defined.
>>> a.angle(7,8)
0.8519663271732721
因此,您可以通过将 *
从 a
导入 b
以及从 b
导入 a
来修复您的代码。您不能将包 xxx
和 b
导入 a
并期望 b
神奇地了解 xxx
。例如,当 b
被导入 a
时,b
不知道 a
,就像 math
不知道它被导入 a
] 并且它 (math
) 无法 "learn" 当 a
导入 math
.
时还有哪些其他包被导入 a
顺便说一句,您可以通过切换 a.py
中的导入顺序轻松再次破解固定版本 1b:
文件'a.py':
from b import * # swap order of imports breaks Version 1b!
import math
在python中,所有模块都有自己的全局命名空间,并且创建了一个包含所有内置名称的命名空间,并且模块不与其他仅内置的命名空间共享,并且可用于所有模块,当您导入一个模块时,它会添加到模块全局命名空间中,而不是内置命名空间中
导入语句做了两件事:
一、如果请求的模块还不存在,则执行导入文件中的代码
two 使它可以作为一个模块使用。后续导入语句将跳过第一步。
要点是模块中的代码将只执行一次,无论它从其他各种模块导入多少次。
a.py:
import numpy as np_patched
def f():
print("patched")
np_patched.array = f
b.py
import a as np_patched
import numpy as np
np.array()
c.py(导入顺序无关紧要?)
import numpy as np
import a as np_patched
np.array()
结果(python3 b.py,或python3 c.py)
patched
解释:
a.py 导入库 X (numpy) 和猴子补丁 X。然后,b.py 导入 a.py。此时,X 对 b.py 不直接可见。在那之后 b.py 导入 X。 Python 不会导入相同的东西两次,所以它继续使用 a.py 中修补的 X 来代替 b.py 而不是导入新的b.py 的 X 副本。这就是为什么 b.py 只得到补丁的 X,而不是原来的 X。
根据我在 and with some information from How to get a reference to current module's attributes in Python 中的实验,我提出了一个实际上可以解决您的导入问题的解决方案。 所有更改都是独占 到文件 a.py
并且 b.py
没有被触及。
解决方案 1:
# in file a.py do this
import xxx
import sys # OR import b (see below)
from b import *
b = sys.modules[fun.__module__] # alternatively, "import b" and drop "import sys" above
# "inject" 'xxx' into 'b':
b.__dict__['xxx'] = globals()['xxx']
解决方案 2:
# in file a.py do this
import xxx
import sys
from b import *
b = sys.modules[fun.__module__] # alternatively, "import b"
# "inject" 'xxx' into 'b':
b.__dict__['xxx'] = sys.modules[__name__].__dict__['xxx']
示例:
文件a.py:
import math # my version of 'xxx'
import sys
from b import *
b = sys.modules[mysq.__module__] # mysq is a function defined in b.py
b.__dict__['math'] = globals()['math']
def angle(x, y):
return math.acos(x / mysq(x*x + y*y))
文件b.py:
def mysq(x):
return math.sqrt(x)
运行:
>>> import a
>>> a.angle(7, 8)
0.8519663271732721
我有两个文件 a.py
和 b.py
。
在 a.py 中, 我们
import xxx
from b import *
在 b.py 中我们有一个需要 module xxx
的函数。
现在,当从 a.py
调用 b.py
中的函数时,它找不到模块 xxx
.
为什么会这样?解决方法是什么?
由于某些原因,我无法在 b.py
中执行 import xxx
。
MCV:
a.py
import xxx
from b import *
fun()
b.py
def fun():
xxx.dosomething()
错误:
Global name xxx not defined
问题:
a.py:
import numpy
print("a.py is imported")
b.py:
import a
numpy.zeros(8)
结果(python3 b.py):
a.py is imported
Traceback (most recent call last):
File "b.py", line 3, in <module>
numpy.zeros(8)
NameError: name 'numpy' is not defined
答案:
我想这更适合编写库。假设a.py是库的一部分,b是使用库的用户程序,库是我写的。如果我在 a.py 中导入的所有内容 (import numpy
) 都显示在 b.py 中,我的库的 API 将不会那么干净,因为我无法隐藏 numpy 库来自我图书馆的用户。我想这就是如果 b.py 导入 a.py.
您可以在 b.py
中导入 xxx如果其名称与您在 b 中导入的另一个文件冲突,请执行以下操作:
import xxx as some_name
并且在 b.py 中,您现在可以将其称为 some_name,即
some_name.run()
这是一组试图模拟您的问题的两个文件。版本 1 是您所描述的,版本 2 是有效的。
版本 1(OP 问题)
文件'a.py':
print("a.py: entered a.py")
import math
print("a.py: imported math")
print("a.py: 1st dir()={}".format(dir()))
from b import *
print("a.py: imported * from b")
print("a.py: 2nd dir()={}".format(dir()))
def angle(x, y):
return math.acos(x/mysq(x*x+y*y))
print("a.py: angle has been defined")
print("a.py: 3rd dir()={}".format(dir()))
import b
print("a.py: dir(b)={}".format(dir(b)))
文件'b.py':
print("b.py: entered b.py")
print("b.py: 1st dir():{}".format(dir()))
def mysq(x):
return math.sqrt(x)
print("b.py: mysq has been defined")
print("b.py: 2nd dir():{}".format(dir()))
print("b.py: leaving b.py...")
然后
>>> import a
a.py: entered a.py
a.py: imported math
a.py: 1st dir()=['__builtins__', '__cached__', '__doc__', '__file__',
'__loader__', '__name__', '__package__', '__spec__',
'math']
b.py: entered b.py
b.py: 1st dir():['__builtins__', '__cached__', '__doc__', '__file__',
'__loader__', '__name__', '__package__', '__spec__']
b.py: mysq has been defined
b.py: 2nd dir():['__builtins__', '__cached__', '__doc__', '__file__',
'__loader__', '__name__', '__package__', '__spec__',
'mysq'] # <-- NOTICE that module 'b' is still hasn't
# loaded 'math' before leaving it!!!
b.py: leaving b.py...
a.py: imported * from b
a.py: 2nd dir()=['__builtins__', '__cached__', '__doc__', '__file__',
'__loader__', '__name__', '__package__', '__spec__',
'math', 'mysq']
a.py: angle has been defined
a.py: 3rd dir()=['__builtins__', '__cached__', '__doc__', '__file__',
'__loader__', '__name__', '__package__', '__spec__',
'angle', 'math', 'mysq']
a.py: dir(b)=['__builtins__', '__cached__', '__doc__', '__file__',
'__loader__', '__name__', '__package__', '__spec__',
'mysq'] # <-- NOTICE that module 'b' is still not aware of 'math'!!!
>>> a.angle(7,8)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/Users/.../a.py", line 9, in angle
return math.acos(x/mysq(x*x+y*y))
File "/Users/.../b.py", line 4, in mysq
return math.sqrt(x)
NameError: name 'math' is not defined
版本 2(工作)
将 import math
放入 b.py
并将其从 a.py
中删除:
文件'a.py':
from b import *
print("a.py: imported * from b")
print("a.py: 1st dir()={}".format(dir()))
def angle(x, y):
return math.acos(x/mysq(x*x+y*y))
print("a.py: angle has been defined")
print("a.py: 2nd dir()={}".format(dir()))
文件'b.py':
print("b.py: entered b.py")
import math
print("b.py: loaded math")
print("b.py: 1st dir():{}".format(dir()))
def mysq(x):
return math.sqrt(x)
print("b.py: mysq has been defined")
print("b.py: 2nd dir():{}".format(dir()))
print("b.py: leaving b.py...")
然后
>>> import a
b.py: entered b.py
b.py: loaded math
b.py: 1st dir():['__builtins__', '__cached__', '__doc__', '__file__',
'__loader__', '__name__', '__package__', '__spec__', 'math']
b.py: mysq has been defined
b.py: 2nd dir():['__builtins__', '__cached__', '__doc__', '__file__',
'__loader__', '__name__', '__package__', '__spec__',
'math', 'mysq']
b.py: leaving b.py...
a.py: imported * from b
a.py: 1st dir()=['__builtins__', '__cached__', '__doc__', '__file__',
'__loader__', '__name__', '__package__', '__spec__',
'math', 'mysq'] # <-- NOTICE 'math' in a.py!!!
a.py: angle has been defined
a.py: 2nd dir()=['__builtins__', '__cached__', '__doc__', '__file__',
'__loader__', '__name__', '__package__', '__spec__',
'angle', 'math', 'mysq']
>>> a.angle(7,8)
0.8519663271732721
我无法准确解释(表述)这种行为背后的机制,但对我来说似乎是合理的:b.py
中的 mysq()
应该如何了解 math
?大量 print
语句的输出表明,在版本 1(OP 问题)中,从 b
导入会导致将 a.py
中 defined/imported 在 [=23] 中的所有内容导入到 a.py
的命名空间中=].整个 b.py
在导入 a.py
时执行一次。但是,b
本身从来没有 "knows" 关于 math
.
在版本 2 中,一切都按预期工作,因为 math
被导入 b
,它在导入 a
时立即执行,并从 [=29= 导入所有内容](包括math
)变成a
.
现在,让我们再做一些实验...让我们破解版本 2:
版本 2b(损坏)
在此版本中,我们将 a.py
修改如下(b.py
与版本 2 相同):
文件'a.py':
import b # <-- We do not import 'math' from b into a!
# Is it still "loaded" somehow into 'a'?
def angle(x, y):
return math.acos(x/b.mysq(x*x+y*y))
导入 "just" b
本身(与从 b
导入所有内容 相反)不会将 math
导入 a
:
>>> a.angle(7,8)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/Users/.../a.py", line 10, in angle
return math.acos(x/b.mysq(x*x+y*y))
NameError: name 'math' is not defined
版本 1b(固定)
最后,让我们通过将 a
中的所有内容导入 b
以及继续将 b
中的所有内容导入 a
来修复版本 1:
文件'a.py':
print("a.py: entered a.py")
import math
print("a.py: imported math")
print("a.py: 1st dir()={}".format(dir()))
from b import *
print("a.py: imported * from b")
print("a.py: 2nd dir()={}".format(dir()))
def angle(x, y):
return math.acos(x/mysq(x*x+y*y))
print("a.py: angle has been defined")
print("a.py: 3rd dir()={}".format(dir()))
import b # extra check of b
print("a.py: dir(b)={}".format(dir(b)))
文件'b.py':
print("b.py: entered b.py")
print("b.py: 1st dir():{}".format(dir()))
from a import *
print("b.py: imported * from a")
print("b.py: 2nd dir():{}".format(dir()))
def mysq(x):
return math.sqrt(x)
print("b.py: mysq has been defined")
print("b.py: 3rd dir():{}".format(dir()))
print("b.py: leaving b.py...")
然后
>>> import a
a.py: entered a.py
a.py: imported math
a.py: 1st dir()=['__builtins__', '__cached__', '__doc__', '__file__',
'__loader__', '__name__', '__package__', '__spec__',
'math'] # 'math' is loaded first into 'a'
b.py: entered b.py
b.py: 1st dir():['__builtins__', '__cached__', '__doc__', '__file__',
'__loader__', '__name__', '__package__', '__spec__'
] # 'b' doesn't "know" yet about 'math'
b.py: imported * from a
b.py: 2nd dir():['__builtins__', '__cached__', '__doc__', '__file__',
'__loader__', '__name__', '__package__', '__spec__',
'math'] # after importing *(!!!) from 'a' into 'b', 'b' now has 'math'
b.py: mysq has been defined
b.py: 3rd dir():['__builtins__', '__cached__', '__doc__', '__file__',
'__loader__', '__name__', '__package__', '__spec__',
'math', 'mysq']
b.py: leaving b.py...
a.py: imported * from b
a.py: 2nd dir()=['__builtins__', '__cached__', '__doc__', '__file__',
'__loader__', '__name__', '__package__', '__spec__',
'math', 'mysq'] # NOTICE: math is not imported twice into 'a'
a.py: angle has been defined
a.py: 3rd dir()=['__builtins__', '__cached__', '__doc__', '__file__',
'__loader__', '__name__', '__package__', '__spec__',
'angle', 'math', 'mysq']
a.py: dir(b)=['__builtins__', '__cached__', '__doc__', '__file__',
'__loader__', '__name__', '__package__', '__spec__',
'math', 'mysq'] # just to make sure, check that 'b' still has 'math' defined.
>>> a.angle(7,8)
0.8519663271732721
因此,您可以通过将 *
从 a
导入 b
以及从 b
导入 a
来修复您的代码。您不能将包 xxx
和 b
导入 a
并期望 b
神奇地了解 xxx
。例如,当 b
被导入 a
时,b
不知道 a
,就像 math
不知道它被导入 a
] 并且它 (math
) 无法 "learn" 当 a
导入 math
.
a
顺便说一句,您可以通过切换 a.py
中的导入顺序轻松再次破解固定版本 1b:
文件'a.py':
from b import * # swap order of imports breaks Version 1b!
import math
在python中,所有模块都有自己的全局命名空间,并且创建了一个包含所有内置名称的命名空间,并且模块不与其他仅内置的命名空间共享,并且可用于所有模块,当您导入一个模块时,它会添加到模块全局命名空间中,而不是内置命名空间中
导入语句做了两件事:
一、如果请求的模块还不存在,则执行导入文件中的代码
two 使它可以作为一个模块使用。后续导入语句将跳过第一步。
要点是模块中的代码将只执行一次,无论它从其他各种模块导入多少次。
a.py:
import numpy as np_patched
def f():
print("patched")
np_patched.array = f
b.py
import a as np_patched
import numpy as np
np.array()
c.py(导入顺序无关紧要?)
import numpy as np
import a as np_patched
np.array()
结果(python3 b.py,或python3 c.py)
patched
解释:
a.py 导入库 X (numpy) 和猴子补丁 X。然后,b.py 导入 a.py。此时,X 对 b.py 不直接可见。在那之后 b.py 导入 X。 Python 不会导入相同的东西两次,所以它继续使用 a.py 中修补的 X 来代替 b.py 而不是导入新的b.py 的 X 副本。这就是为什么 b.py 只得到补丁的 X,而不是原来的 X。
根据我在 a.py
并且 b.py
没有被触及。
解决方案 1:
# in file a.py do this
import xxx
import sys # OR import b (see below)
from b import *
b = sys.modules[fun.__module__] # alternatively, "import b" and drop "import sys" above
# "inject" 'xxx' into 'b':
b.__dict__['xxx'] = globals()['xxx']
解决方案 2:
# in file a.py do this
import xxx
import sys
from b import *
b = sys.modules[fun.__module__] # alternatively, "import b"
# "inject" 'xxx' into 'b':
b.__dict__['xxx'] = sys.modules[__name__].__dict__['xxx']
示例:
文件a.py:
import math # my version of 'xxx'
import sys
from b import *
b = sys.modules[mysq.__module__] # mysq is a function defined in b.py
b.__dict__['math'] = globals()['math']
def angle(x, y):
return math.acos(x / mysq(x*x + y*y))
文件b.py:
def mysq(x):
return math.sqrt(x)
运行:
>>> import a
>>> a.angle(7, 8)
0.8519663271732721