Crea un processo eseguibile senza usare la shell su Python 2.5 e precedenti
-
05-07-2019 - |
Domanda
Proprio quello che dice il titolo:
- Il modulo
subprocess
non può essere utilizzato in quanto dovrebbe funzionare su 2.4 e 2.5 - Il processo di shell non deve essere generato per passare argomenti.
Per spiegare (2), considera il seguente codice:
>>> x=os.system('foo arg')
sh: foo: not found
>>> x=os.popen('foo arg')
sh: foo: not found
>>>
Come puoi vedere os.system
e os.popen
esegue il comando dato (" foo ") tramite una shell di sistema (" sh "). Non voglio che ciò accada (altrimenti, i brutti messaggi "non trovati" vengono stampati per programmare stderr senza il mio controllo).
Infine, dovrei essere in grado di passare argomenti a questo programma ('arg' nell'esempio sopra).
Come si potrebbe fare in Python 2.5 e 2.4?
Soluzione
Probabilmente dovrai usare il modulo di sottoprocesso che è disponibile in Python 2.4
Popen("/home/user/foo" + " arg")
>>> Popen("foo arg", shell=False)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/lib/python2.6/subprocess.py", line 595, in __init__
errread, errwrite)
File "/usr/lib/python2.6/subprocess.py", line 1092, in _execute_child
raise child_exception
OSError: [Errno 2] No such file or directory
Dovrai includere il percorso completo poiché non stai usando la shell.
http://docs.python.org/library/subprocess .html # sostituendo-os-system
In alternativa puoi anche passare subprocess.PIPE a stderr e stdout per sopprimere i messaggi. Vedi il link sopra per maggiori dettagli.
Altri suggerimenti
Come precedentemente descritto, puoi (e dovresti) utilizzare il modulo subprocess .
Per impostazione predefinita, il parametro shell
è False
. Questo è buono e abbastanza sicuro. Inoltre, non è necessario passare il percorso completo, basta passare il nome eseguibile e gli argomenti come sequenza (tupla o elenco).
import subprocess
# This works fine
p = subprocess.Popen(["echo","2"])
# These will raise OSError exception:
p = subprocess.Popen("echo 2")
p = subprocess.Popen(["echo 2"])
p = subprocess.Popen(["echa", "2"])
Puoi anche usare queste due funzioni di convenienza già definite nel modulo di sottoprocesso:
# Their arguments are the same as the Popen constructor
retcode = subprocess.call(["echo", "2"])
subprocess.check_call(["echo", "2"])
Ricorda che puoi reindirizzare stdout
e / o stderr
su PIPE
, e quindi non verrà stampato sullo schermo (ma il l'output è ancora disponibile per la lettura dal tuo programma python). Per impostazione predefinita, stdout
e stderr
sono entrambi None
, il che significa nessun reindirizzamento , il che significa che useranno lo stesso stdout / stderr come programma python.
Inoltre, puoi usare shell = True
e reindirizzare stdout
. stderr
su un PIPE, e quindi nessun messaggio verrà stampato:
# This will work fine, but no output will be printed
p = subprocess.Popen("echo 2", shell=True,
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
# This will NOT raise an exception, and the shell error message is redirected to PIPE
p = subprocess.Popen("echa 2", shell=True,
stdout=subprocess.PIPE, stderr=subprocess.PIPE)