Estoy buscando una forma de pasar varias opciones usando runpy u otras herramientas.
En particular, me gustaría obtener el resultado de una secuencia de comandos de Python optimizada en otra secuencia de comandos de Python no optimizada.
python -O tobeoptimized.pyIntenté usar el subproceso pero no puedo extraer el objeto que necesito como lo hago en runpy.
from subprocess import PIPE, run command = ['python','-O','tobeoptimized.py'] result = run(command, stdout=PIPE, stderr=PIPE, universal_newlines=True)No con runpy porque no genera un nuevo proceso , ( exec() ). Si se hubiera podido hacer así, esta pregunta habría tenido respuesta. Por lo tanto, estamos cayendo en el mundo de la base de código o extensión de C, donde el núcleo de CPython se modifica de tal manera que se puede acceder al menos desde la API de C, si no desde la API de Python.
En su lugar, intente usar el subproceso para pasar las banderas. La salida se puede ajustar.
Si el problema es que desea extraer un objeto del proceso (por lo tanto, el subproceso "falla"), debe buscar en el módulo pickle o simplemente colocarlo en un archivo/búfer/socket y recuperar los datos + volver a ensamblar en un personalizado conducta.
El subproceso no es realmente obligatorio, sin embargo, si hubiera alguna otra implementación, no lo "hackearía" porque es el núcleo compilado lo que está en el camino, no algo que pueda ser parcheado.
¿Supongo que necesitamos una nueva característica de los desarrolladores principales? :)
Con respecto a la salida del subproceso, esto funciona bien para mí.
# 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())Es factible.
La función incorporada de compile toma el parámetro de optimización . Sus valores son 0 es como sin -O , 1 es -O y 2 es -OO .
Para optimizar el módulo / ruta de ejecución runpy , se debe parchear. Antes de hacerlo, definiré dos funciones para ilustración.
Este es un módulo de prueba. Si se ejecuta sin optimización, no se imprimirá.
app.py
assert 0, "assert zero" print("Optimized") Estas dos funciones no hacen todos los detalles como lo hace runpy . Así que no funcionará en su totalidad.
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 Este es para parchear una función en runpy que runpy.run_module usa para ejecutar el objeto de código del módulo. El parche proporciona un objeto de código optimizado.
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') ACTUALIZAR
runpy.run_path se puede ejecutar con la optimización activada.
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")