web-dev-qa-db-fra.com

Utilisation d'un sous-processus pour exécuter Python sous Windows

Existe-t-il un moyen simple d'exécuter un script Python sous Windows/Linux/OS X?

Sur les deux derniers, subprocess.Popen("/the/script.py") fonctionne, mais sur Windows j'obtiens l'erreur suivante:

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

de monkut commentaire : Le cas d'utilisation n'est pas clair. Pourquoi utiliser un sous-processus pour exécuter un script python? Y a-t-il quelque chose qui vous empêche d'importer le script et d'appeler la fonction nécessaire?

J'écrivais un script rapide pour tester la fonctionnalité globale d'un outil en ligne de commande Python (pour le tester sur différentes plates-formes). Fondamentalement, il devait créer un tas de fichiers dans un dossier temporaire, exécuter le script à ce sujet et vérifier que les fichiers étaient renommés correctement.

J'aurais pu importer le script et appeler la fonction, mais comme il repose sur sys.argv Et utilise sys.exit(), j'aurais dû faire quelque chose comme ..

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

De plus, je voulais capturer la stdout et la stderr pour le débogage en cas de problème.

Bien sûr, une meilleure façon serait d'écrire le script de manière plus testable par unité, mais le script est essentiellement "terminé" et je fais un dernier lot de tests avant de faire une version "1.0" (après quoi je vais pour faire une réécriture/restructuration, qui sera beaucoup plus ordonnée et plus testable)

Fondamentalement, il était beaucoup plus facile d'exécuter simplement le script en tant que processus, après avoir trouvé la variable sys.executable. Je l'aurais écrit sous forme de script Shell, mais cela n'aurait pas été multiplateforme. Le script final peut être trouvé ici

38
dbr

Viens juste de trouver sys.executable - le chemin complet vers l'exécutable Python exécutable, qui peut être utilisé pour exécuter le script (au lieu de s'appuyer sur le shbang, qui ne fonctionne évidemment pas sous Windows)

import sys
import subprocess

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

Que dis-tu de ça:

import sys
import subprocess

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

Cela indique à subprocess d'utiliser le shell du système d'exploitation pour ouvrir votre script et fonctionne sur tout ce que vous pouvez simplement exécuter dans cmd.exe.

De plus, cela recherchera dans le CHEMIN "myscript.py" - ce qui pourrait être souhaitable.

21
Roman Starkov

Oui subprocess.Popen(cmd, ..., Shell=True) fonctionne comme un charme. Sous Windows, le .py l'extension de fichier est reconnue, donc Python est invoqué pour le traiter (sur * NIX juste le Shebang habituel). L'environnement du chemin contrôle si les choses sont vues. Donc le premier argument de Popen est juste le nom du script.

subprocess.Popen(['myscript.py', 'arg1', ...], ..., Shell=True)
6
hmc

Il semble que Windows essaie d'exécuter le script en utilisant son propre framework EXE plutôt que de l'appeler comme

python /the/script.py

Essayer,

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

Edit: "python" devrait être sur votre chemin.

4
viksit

Vous utilisez un séparateur de chemin qui dépend de la plate-forme. Windows utilise "\" et Unix utilise "/".

2
user59634

Par exemple, pour exécuter le suivant avec l'invite de commande ou le fichier BATCH, nous pouvons utiliser ceci:

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

Même chose avec Python, on peut faire ça:

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

ou

subprocess.Popen(['C:/Python27/python.exe', 'C:/Program files(x86)/dev_appserver.py', '--Host', '0.0.0.0', '--port', '8080', 'C:/blabla'], Shell=True)
2
YumYumYum

Lorsque vous exécutez un script python sur les fenêtres du sous-processus, vous devez utiliser python devant le nom du script. Essayez:

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