使用 exec 来运行模块文件
严格地说,除了已展示过的方式,还有更多方式来运行模块文件中的代码。比如, exec(open('module.py').read())
内置函数调用就是在交互式提示符下启动文件的另一种方法,无需导入和随后的重载。每个这种 exec
运行从文件中读取的代码的当前版本,而无需随后的重载( script1.py 如我们之前一节重载后那样):
% python
>>> exec(open('script1.py').read())
win32
65536
Spam!Spam!Spam!Spam!Spam!Spam!Spam!Spam!
...Change script1.py in a text edit window to print 2 ** 32...
>>> exec(open('script1.py').read())
win32
4294967296
Spam!Spam!Spam!Spam!Spam!Spam!Spam!Spam!
exec
调用有类似于导入的效果,但它并不真的导入模块——默认地,每次这样调用 exec
时,它重新运行文件的代码,好像你将它粘贴在 exec
被调用的地方。因为这个原因, exec
在文件改变后无需模块重载——它略过了通常的模块导入逻辑。
不利的是,因为它就像你粘贴代码到 exec 被调用的地方,就像之前提到的 from
语句,可能默默地覆盖当前可能正在使用的变量。比如,script1.py 分配了一个名为 x 的变量。如果那个名字也正在 exec 被调用的地方被使用,那个名字的值就会被替换:
>>> x = 999
>>> exec(open('script1.py').read()) # Code run in this namespace by default
...same output...
>>> x # Its assignments can overwrite names here
'Spam!'
作为对比,基本的 import
语句只在一个进程运行文件一次,且它让文件成为一个单独的模块命名空间以至于它的赋值不会改变当前范围中的变量。模块的命名空间分隔的代码是需要修改代码后重载。