模块被重复导入。Python解释器可能存在漏洞
我在我的一个项目中做了一个比较复杂的导入方案,觉得可能发现了Python解释器的一个bug,这个bug会导致模块被导入两次。
下面是我的测试项目的结构:
/
Launcher.bat — 从这里运行项目。它使用Python 3.2的可执行文件来启动'main/__init__.py'
main/__init__.py — 这是
__main__
脚本,也就是'Launcher.bat'启动的那个脚本main/foo.py — 里面有一个空的类
external/__init__.py — 这是一个外部脚本,用来演示问题
./Launcher.bat
@echo off
C:\Python32\python.exe main\__init__.py
pause
./main/__init__.py
from foo import Foo
print("In 'main', Foo has id:", id(Foo))
# Add the directory from which 'Launcher.bat' was run,
# which is not the same as the './main' directory
# in which this script is located
import sys
sys.path.insert(1, '.')
# This script will try to import class Foo, but in doing so
# will casue the interpreter to import this './main/__init__.py'
# script a second time.
__import__('external')
./main/foo.py
class Foo:
pass
./external/__init__.py
from main.foo import Foo
print("In 'external', Foo has id:", id(Foo))
这些代码会打印出'主脚本被导入'
的信息两次。如果外部脚本导入了其他脚本,那些脚本也会被导入两次。我只在Python 3.2上测试过这个。请问这是个bug,还是我做错了什么?
程序的输出是:
在'main'中,Foo的ID是:12955136
在'main'中,Foo的ID是:12955136
在'external'中,Foo的ID是:12957456
按任意键继续 . . .
2 个回答
2
我觉得这不是个错误。你应该去 python-dev
的讨论组问一下,那里能得到更权威的答案。你运行脚本的时候执行了一次,然后从外部导入的时候又执行了一次,所以那行代码被打印了两次。其实并不是导入了两次。
不过,这样的设置真是糟糕透了。这里有很多不符合规范的地方。虽然有些是为了演示目的,但整体看起来还是很乱。
- 你不应该把包的
__init__.py
文件当成一个需要运行的文件。主要的入口应该是一个导入这个包的脚本。 - 你不应该让一个被导入的模块去导入它所依赖的模块,就像你外部模块对主模块所做的那样。