运行 来自另一个 Python 脚本的处于优化模式的 Python 脚本

Running a Python script in optimized mode from another Python script

有没有办法从另一个 Python (Python 3) 脚本 运行 优化模式下的 python 脚本?

如果我有以下 test.py 脚本(读取 built-in constant __debug__):

if __debug__:
    print('Debug ON')
else:
    print('Debug OFF')

然后:

因为 constant __debug__ 的工作原理:

This constant is true if Python was not started with an -O option. See also the assert statement.

此外,__debug__ 的值无法在 运行 时更改:__debug__ 是一个常量,如文档 here and here 中所述。 __debug__ 的值在 Python 解释器启动时确定。

以下正确打印 Debug OFF

import subprocess
subprocess.run(["python", "-OO", "test.py"])

但是有没有更pythonic的方法呢? 如果不调用解释器 python.

,上面的代码看起来不太便携

我已经在这里和网上搜索过,但没有成功。

使用compile

我想出了一个使用内置函数 compile 的解决方案,如下所示。

文件内容 main.py:

with open('test.py') as f:
    source_code = f.read()
compiled = compile(
    source_code,
    filename='test.py', mode='exec', optimize=2)
exec(compiled)

文件内容 test.py:

if __debug__:
    print('Debug ON')
else:
    print('Debug OFF')

运行ning python main.py 的输出是:

Debug OFF

参数的可能值 optimize:

  • -1:使用与 Python 解释器相同的优化级别,即 运行 宁函数 compile
  • 0:没有优化,__debug__ == true
  • 1:类似于 -O,即删除 assert 语句,以及 __debug__ == false
  • 2:像 -OO,即也删除文档字符串。

不知道这是否是最佳选择,如果对其他人有用,请分享。

使用subprocess.run

基于 subprocess 的方法仍然更加简洁,并且可以通过使用 sys.executable:

实现可移植性
import subprocess
import sys

if not sys.executable:
    raise RuntimeError(sys.executable)
proc = subprocess.run(
    [sys.executable, '-OO', 'test.py'],
    capture_output=True, text=True)
if proc.returncode != 0:
    raise RuntimeError(proc.returncode)

以上代码调用函数subprocess.run.

检查变量sys.executable的值是由CPython的documentation引发的:

If Python is unable to retrieve the real path to its executable, sys.executable will be an empty string or None.

检查是使用 raise 语句而不是 assert 语句实现的,以便在上述 Python 代码本身 运行 从 Python 请求优化,例如,通过使用 python -O or python -OO or the environment variable PYTHONOPTIMIZE.

When optimization is requested, assert statements are removed.

使用 raise 语句还可以引发 AssertionError 以外的异常,在本例中为 RuntimeError.

对于同一源文件内的函数内的 运行ning Python 代码(即,在 main.py 内,而不是在 test.py 内),函数 inspect.getsource can be used, together with the option -c of python.

顺便欢迎更好的回答!