Ejecutar un script python desde otro script python, pasando args [duplicate]


Esta pregunta ya tiene una respuesta aquí:

Quiero ejecutar un script Python desde otro script Python. Quiero pasar variables como lo haría usando la línea de comandos.

Por ejemplo, ejecutaría mi primer script que iteraría a través de una lista de valores (0,1,2,3) y pasarlos al 2do script script2.py 0 luego script2.py 1, etc.

Lo encontré 1186789 que es una pregunta similar, pero la respuesta de ars llama a una función, donde como quiero ejecutar todo el script no solo una función, y la respuesta de balpha llama al script pero sin args. Alteré esto a algo como lo siguiente como una prueba:

execfile("script2.py 1")

Pero no está aceptando variables correctamente. Cuando imprimo el sys.argv en script2.py es la llamada de comando original al primer script "['C:\script1.py"].

Realmente no quiero cambiar el script original (i. e. script2.py en mi ejemplo) ya que no lo poseo.

Me imagino que debe haber una manera de hacer esto, solo estoy confundido cómo lo haces.

 235
Author: Community, 2010-09-23

7 answers

Intente usar os.system:

os.system("script2.py 1")

execfile es diferente porque está diseñado para ejecutar una secuencia de sentencias Python en el contexto de ejecución actual . Es por eso que sys.argv no cambió para ti.

 257
Author: Greg Hewgill,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-09-23 19:33:16

Esto es inherentemente lo incorrecto. Si está ejecutando un script Python desde otro script Python, debe comunicarse a través de Python en lugar de a través del sistema operativo:

import script1

En un mundo ideal, usted será capaz de llamar a una función dentro de script1 directamente:

for i in range(whatever):
    script1.some_function(i)

Si es necesario, puede hackear sys.argv. Hay una forma ordenada de hacer esto usando un administrador de contexto para asegurarse de que no realice ningún cambio permanente.

import contextlib
@contextlib.contextmanager
def redirect_argv(num):
    sys._argv = sys.argv[:]
    sys.argv=[str(num)]
    yield
    sys.argv = sys._argv

with redirect_argv(1):
    print(sys.argv)

Creo que esto es preferible a pasar todo sus datos al sistema operativo y viceversa; eso es una tontería.

 84
Author: Katriel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-09-23 19:48:55

Idealmente, el script Python que desea ejecutar se configurará con código como este cerca del final:

def main(arg1, arg2, etc):
    # do whatever the script does


if __name__ == "__main__":
    main(sys.argv[1], sys.argv[2], sys.argv[3])

En otras palabras, si se llama al módulo desde la línea de comandos, analiza las opciones de la línea de comandos y luego llama a otra función, main(), para hacer el trabajo real. (Los argumentos reales variarán, y el análisis puede ser más complicado.)

Si desea llamar a un script de este tipo desde otro script de Python, sin embargo, puede simplemente import y llamar a modulename.main() directamente, en lugar que pasar por el sistema operativo.

os.system funcionará, pero es la forma indirecta (léase "lento") de hacerlo, ya que está comenzando un nuevo proceso de intérprete de Python cada vez para no raisin.

 74
Author: kindall,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-12-29 18:29:12

Subproceso module:
http://docs.python.org/dev/library/subprocess.html#using-the-subprocess-module

import subprocess
subprocess.Popen("script2.py 1", shell=True)

Con esto, también puede redirigir stdin, stdout y stderr.

 36
Author: Chris Adams,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-09-23 19:36:17

Creo que la buena práctica puede ser algo como esto:

import subprocess
cmd = 'python script.py'

p = subprocess.Popen(cmd, stdout=subprocess.PIPE, shell=True)
out, err = p.communicate() 
result = out.split('\n')
for lin in result:
    if not lin.startswith('#'):
        print(lin)

Según la documentación El módulo subprocess le permite generar nuevos procesos, conectarse a sus tuberías de entrada / salida / error y obtener sus códigos de retorno. Este módulo pretende reemplazar varios módulos y funciones más antiguos:

os.system
os.spawn*
os.popen*
popen2.*
commands.*

Usa communicate() en lugar de .stdin.escribir, .stdout.leer o .stderr.lea para evitar bloqueos debido a que cualquiera de los otros búferes de tuberías del sistema operativo se llena y bloquea al niño proceso. Lea aquí

 31
Author: Medhat Helmy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-02-22 11:44:51
import subprocess
subprocess.call(" python script2.py 1", shell=True)
 24
Author: Nikos,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-11-12 12:26:10

Si os.el sistema no es lo suficientemente potente para ti, existe el módulo de subproceso.

 3
Author: nmichaels,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-09-23 19:37:51