2009-05-26 17 views
34

¿Existe una manera simple de ejecutar un script de Python en Windows/Linux/OS X?Uso del subproceso para ejecutar el script de Python en Windows

En los dos, subprocess.Popen("/the/script.py") último funciona, pero en Windows Me sale el siguiente error:

Traceback (most recent call last): 
    File "test_functional.py", line 91, in test_functional 
    log = tvnamerifiy(tmp) 
    File "test_functional.py", line 49, in tvnamerifiy 
    stdout = PIPE 
    File "C:\Python26\lib\subprocess.py", line 595, in __init__ 
    errread, errwrite) 
    File "C:\Python26\lib\subprocess.py", line 804, in _execute_child 
    startupinfo) 
WindowsError: [Error 193] %1 is not a valid Win32 application 

monkut's comment: The use case isn't clear. Why use subprocess to run a python script? Is there something preventing you from importing the script and calling the necessary function?

estaba escribiendo un guión rápida para probar la funcionalidad general de un pitón mando herramienta de línea (para probarlo en varias plataformas). Básicamente, tenía que crear un grupo de archivos en una carpeta temporal, ejecutar la secuencia de comandos y verificar que los archivos se hayan cambiado de nombre correctamente.

que podría haber importado el guión y se llama a la función, pero ya que se basa en sys.argv y utiliza sys.exit(), habría necesitado para hacer algo así ..

import sys 
import tvnamer 
sys.argv.append("-b", "/the/folder") 
try: 
    tvnamer.main() 
except BaseException, errormsg: 
    print type(errormsg) 

Además, quería capturar la salida estándar y stderr para la depuración en caso de que algo salga mal.

Por supuesto, una mejor manera sería escribir el guión de forma más comprobable por unidad, pero el guión está básicamente "hecho" y estoy haciendo un último lote de pruebas antes de hacer un lanzamiento de "1.0" (después de lo cual Voy a hacer una reescritura/reestructuración, que será mucho más ordenada y más comprobable)

Básicamente, era mucho más fácil simplemente ejecutar el script como un proceso, después de encontrar la variable sys.executable. Lo habría escrito como un script de shell, pero eso no habría sido multiplataforma. El guión final se puede encontrar here

+2

El caso de uso no está claro. ¿Por qué usar un subproceso para ejecutar un script python? ¿Hay algo que le impida importar la secuencia de comandos y llamar a la función necesaria? – monkut

+0

Tenía el mismo problema al ejecutar los módulos de nodejs de python. subprocess.call ([r '.. \ nodejs \ npm'], shell = True) resolvió el problema. – Stefan

Respuesta

52

acaba de encontrar sys.executable - la ruta completa al ejecutable de Python actual, que puede ser utilizado para ejecutar el script (en lugar de confiar en el shbang, lo que obviamente no funciona en Windows)

import sys 
import subprocess 

theproc = subprocess.Popen([sys.executable, "myscript.py"]) 
theproc.communicate() 
+3

podría usar 'subprocess.check_call ([sys.executable," myscript.py "])' en su lugar. – jfs

1

Cuando ejecuta un script de python en Windows en subproceso, debe usar python delante del nombre del script. Proveedores:

process = subprocess.Popen("python /the/script.py") 
4

Parece que Windows intenta ejecutar la secuencia de comandos con su propio marco EXE en lugar de llamarlo como

python /the/script.py 

intento,

subprocess.Popen(["python", "/the/script.py"]) 

Editar: "pitón" sería necesita estar en tu camino.

+0

El instalador de Windows python.org no parece poner el comando "python" en PATH, y creo que tendría el sufijo .exe (que rompería las otras plataformas) – dbr

+0

ah, supongo que el .exe rompería las cosas , sí ... – viksit

+0

Hm, parece que puedes excluir el .exe en Windows, siempre y cuando esté en PATH, pero tienes que agregar manualmente Python al mismo – dbr

2

Está utilizando un separador de nombre de ruta que depende de la plataforma. Windows usa "\" y Unix usa "/".

+0

Buen punto, aunque en el script real que causó el error usé os.path.join() (aunque debería haberlo mencionado) – dbr

+5

Por supuesto, la barra diagonal ha sido válida en Windows desde tiempos prehistóricos y todavía lo es, entonces eso es no es un problema. –

+0

@romkyns no realmente: subprocess.call ([r '.. \ nodejs \ npm'], shell = True) funciona, mientras que subprocess.call (['../ nodejs/npm'], shell = True) da ' .. 'no se reconoce como el comando interno o externo – Stefan

20

¿Qué tal esto:

import sys 
import subprocess 

theproc = subprocess.Popen("myscript.py", shell = True) 
theproc.communicate()     # ^^^^^^^^^^^^ 

Esto le dice subprocess para usar el intérprete OS para abrir la secuencia de comandos, y trabaja en algo que sólo puede funcionar en cmd.exe.

Además, esto buscará en la RUTA "myscript.py" - que podría ser deseable.

+0

Creo que funcionará igual, si recuerdo right shell = True solo detiene el subproceso para evitar caracteres especiales (por lo que "mycmd> somefile.txt" redirige el texto a somefile.txt, en lugar de intentar ejecutar un archivo llamado " mycmd> somefile.txt ") – dbr

+2

Aquí hay una situación en la que los dos son significativamente diferentes. Supongamos que "myscript.py" está en el sistema PATH, y no en el directorio actual. Si usa "shell = True", el script se encontrará en la RUTA, pero si usa "sys.executable" no lo hará. –

+0

Ahh entiendo lo que quiere decir (aunque el script que estaba tratando de ejecutar siempre iba a estar en el directorio actual) – dbr

5

subprocess.Popen(cmd, ..., shell=True) funciona como un encanto. En Windows, se reconoce la extensión de archivo .py, por lo que se invoca a Python para procesarla (en * NIX solo el shebang usual). El entorno de ruta controla si se ven las cosas. Entonces, la primera arg a Popen es solo el nombre de la secuencia de comandos.

subprocess.Popen(['myscript.py', 'arg1', ...], ..., shell=True) 
+0

'shell = True # no muestra el símbolo del sistema, entonces true, si es falso, muéstralo' – YumYumYum

1

Por ejemplo, para ejecutar siguiendo con la línea de comandos o archivo por lotes que podemos utilizar esto:

C:\Python27\python.exe "C:\Program files(x86)\dev_appserver.py" --host 0.0.0.0 --post 8080 "C:\blabla\" 

Lo mismo que ver con Python, podemos hacer esto:

subprocess.Popen(['C:/Python27/python.exe', 'C:\\Program files(x86)\\dev_appserver.py', '--host', '0.0.0.0', '--port', '8080', 'C:\\blabla'], shell=True) 

o

subprocess.Popen(['C:/Python27/python.exe', 'C:/Program files(x86)/dev_appserver.py', '--host', '0.0.0.0', '--port', '8080', 'C:/blabla'], shell=True) 
Cuestiones relacionadas