10

我正在寻找一种使用runpy或其他工具传递杂项选项的方法。

特别是,我想在另一个未优化的 python 脚本中获得优化的 python 脚本的输出。

python -O tobeoptimized.py

我尝试过使用子进程,但我无法像在 runpy 中那样提取我需要的对象。

from subprocess import PIPE, run
command = ['python','-O','tobeoptimized.py']
result = run(command, stdout=PIPE, stderr=PIPE, universal_newlines=True)
4

2 回答 2

6

不是runpy因为它没有产生新进程exec())。如果可以这样做,这个问题就会有答案。因此,我们几乎陷入了 C 代码库或扩展世界,其中 CPython 的核心以这样的方式进行了修改,如果不能从 Python API 访问,至少可以从 C API 访问它。

而是尝试使用子进程来传递标志。可以调整输出。

如果问题是您想从进程中提取对象(因此子进程“失败”),您需要查看pickle模块或简单地将其放入文件/缓冲区/套接字并检索数据+以自定义方式重新组装.

子进程并不是真正强制性的,但是如果有任何其他实现,它不会“破解”它,因为它是编译的核心,而不是可以通过猴子修补的东西。

我想我们需要核心开发人员的新功能?:)

关于子流程输出,这对我来说很好。

# hello.py
print("Hello")
# main.py
from subprocess import Popen, PIPE

process = Popen(
    ["python", "-O", "hello.py"],
    stdout=PIPE, stderr=PIPE, universal_newlines=True
)
print(process.stdout.read())
于 2021-07-14T13:51:19.187 回答
4

这是可行的。内置函数采用
优化参数。它的值就像没有, is和is 。 要优化运行模块/路径,必须对其进行修补。在此之前,我将定义两个函数进行说明。compile0-O1-O2-OO
runpy

这是一个测试模块。如果它在没有优化的情况下运行,它将不会打印。
应用程序.py

assert 0, "assert zero"
print("Optimized")

这两个函数并没有像现在那样做所有的细节runpy。所以不能完全发挥作用。

import importlib
import runpy

optimize = 1


def run_module(mod_name):
    spec = importlib.util.find_spec(mod_name)
    source = spec.loader.get_source(spec.name)
    code = compile(source, spec.name + ".py", "exec", optimize=optimize)
    d = {}
    exec(code, d)
    return d


def run_path(path):
    with open(path) as f:
        source = f.read()
    code = compile(source, path, "exec", optimize=optimize)
    d = {}
    exec(code, d)
    return d

这是修补一个函数,runpy用于runpy.run_module获取要运行的模块的代码对象。该补丁提供了优化的代码对象。

import runpy

optimize = 1

def _get_module_details_wrapper(func):
    def tmp(*args, **kwargs):
        mod_name, spec, _ = func(*args, **kwargs)
        source = spec.loader.get_source(spec.name)
        code = compile(source, spec.name + ".py", "exec", optimize=optimize)
        return mod_name, spec, code

    return tmp

runpy._get_module_details = _get_module_details_wrapper(runpy._get_module_details)
runpy.run_module('app')

UPDATE
runpy.run_path可以在优化开启的情况下运行。

def optimize_compile(o):
    from functools import partial
    import builtins

    builtins.compile = partial(compile, optimize=o)


optimize_compile(1)
runpy.run_path("app.py")


optimize_compile(0)
try:
    runpy.run_path("app.py")
except AssertionError:
    print("assertion")

optimize_compile(1)
runpy.run_path("app.py")
于 2021-07-20T06:11:59.283 回答