使用 exec 来运行模块文件

严格地说,除了已展示过的方式,还有更多方式来运行模块文件中的代码。比如, <font style="color:rgb(133, 128, 128);background-color:rgb(249, 250, 250);">exec(open('module.py').read())</font> 内置函数调用就是在交互式提示符下启动文件的另一种方法,无需导入和随后的重载。每个这种 <font style="color:rgb(133, 128, 128);background-color:rgb(249, 250, 250);">exec</font> 运行从文件中读取的代码的当前版本,而无需随后的重载( script1.py 如我们之前一节重载后那样):
  1. % python
  2. >>> exec(open('script1.py').read())
  3. win32
  4. 65536
  5. Spam!Spam!Spam!Spam!Spam!Spam!Spam!Spam!
  6. ...Change script1.py in a text edit window to print 2 ** 32...
  7. >>> exec(open('script1.py').read())
  8. win32
  9. 4294967296
  10. Spam!Spam!Spam!Spam!Spam!Spam!Spam!Spam!

<font style="color:rgb(133, 128, 128);background-color:rgb(249, 250, 250);">exec</font> 调用有类似于导入的效果,但它并不真的导入模块 —— 默认地,每次这样调用 <font style="color:rgb(133, 128, 128);background-color:rgb(249, 250, 250);">exec</font> 时,它重新运行文件的代码,好像你将它粘贴在 <font style="color:rgb(133, 128, 128);background-color:rgb(249, 250, 250);">exec</font> 被调用的地方。因为这个原因, <font style="color:rgb(133, 128, 128);background-color:rgb(249, 250, 250);">exec</font> 在文件改变后无需模块重载 —— 它略过了通常的模块导入逻辑。

不利的是,因为它就像你粘贴代码到 exec 被调用的地方,就像之前提到的 <font style="color:rgb(133, 128, 128);background-color:rgb(249, 250, 250);">from</font> 语句,可能默默地覆盖当前可能正在使用的变量。比如,script1.py 分配了一个名为 x 的变量。如果那个名字也正在 exec 被调用的地方被使用,那个名字的值就会被替换:
  1. >>> x = 999
  2. >>> exec(open('script1.py').read()) # Code run in this namespace by default
  3. ...same output...
  4. >>> x # Its assignments can overwrite names here
  5. 'Spam!'
作为对比,基本的 <font style="color:rgb(133, 128, 128);background-color:rgb(249, 250, 250);">import</font> 语句只在一个进程运行文件一次,且它让文件成为一个单独的模块命名空间以至于它的赋值不会改变当前范围中的变量。模块的命名空间分隔的代码是需要修改代码后重载。

使用 exec 来运行模块文件——注意

版本差异说明:除了允许形式 <font style="color:rgb(133, 128, 128);background-color:rgb(249, 250, 250);">exec(open('module.py'))</font>,Python 2.X 也包含了一个 <font style="color:rgb(133, 128, 128);background-color:rgb(249, 250, 250);">execfile('module.py')</font> 内置函数,它们两个都自动读取文件的内容。这两种形式都等价于 <font style="color:rgb(133, 128, 128);background-color:rgb(249, 250, 250);">exec(open('module.py').read())</font> 形式,它更复杂但在 2.X 和 3.X 中都可以运行。

不幸的是,这两种更简单的 2.X 形式在 3.X 中都不可用,这意外着必须理解文件和他们的读取方法来完全理解当今的这个技术(这似乎是 3.X 中美学大于实用性的一个案例)。事实上,在 3.X 中的 <font style="color:rgb(133, 128, 128);background-color:rgb(249, 250, 250);">exec</font> 形式涉及到如此多的输入以至于最好的建议可能是不要使用它 —— 通过输入系统 shell 命令行或通过使用在下一节中描述的 IDLE 目录选项来启动文件通常更简单。 要获取关于被 3.X <font style="color:rgb(133, 128, 128);background-color:rgb(249, 250, 250);">exec</font> 形式使用的文件接口的更多信息,参见第 9 章。要获取关于 <font style="color:rgb(133, 128, 128);background-color:rgb(249, 250, 250);">exec</font> 和它的两个类似命令 <font style="color:rgb(133, 128, 128);background-color:rgb(249, 250, 250);">eval</font><font style="color:rgb(133, 128, 128);background-color:rgb(249, 250, 250);">compile</font> 的更多信息,参见第 10 章和第 25 章。