2014-06-19 4 views
18

Je dois exécuter la commande date | grep -o -w '"+tz+"'' | wc -w en utilisant Python sur mon hôte local. J'utilise le module subprocess pour le même et en utilisant la méthode check_output que j'ai besoin de capturer la sortie pour le même.Erreur de fichier introuvable lors du lancement d'un sous-processus

Cependant, il me lancer une erreur:

Traceback (most recent call last): 
    File "test.py", line 47, in <module> 
    check_timezone() 
    File "test.py", line 40, in check_timezone 
    count = subprocess.check_output(command) 
    File "/usr/lib/python2.7/subprocess.py", line 537, in check_output 
    process = Popen(stdout=PIPE, *popenargs, **kwargs) 
    File "/usr/lib/python2.7/subprocess.py", line 679, in __init__ 
    errread, errwrite) 
    File "/usr/lib/python2.7/subprocess.py", line 1249, in _execute_child 
    raise child_exception- 
OSError: [Errno 2] No such file or directory 

S'il vous plaît aider là où je vais mal. Je suis nouveau sur python

+0

Pouvez-vous poster la ligne (s) qui jette l'erreur? – wnnmaw

+0

@wnnmaw 'subprocess.check_output (commande)' où la commande est telle que mentionnée dans OP – h4ck3d

+0

Comment définissez-vous la valeur de 'command'? (Il n'est pas clair comment toutes les guillemets simples et doubles dans l'OP s'alignent.) Quelle est la valeur de 'tz'? – chepner

Répondre

38

Vous devez ajouter shell=True pour exécuter une commande shell. check_output essaie de trouver un exécutable appelé: date | grep -o -w '"+tz+"'' | wc -w et il ne peut pas le trouver. (aucune idée de la raison pour laquelle vous avez supprimé les informations essentielles du message d'erreur).

Voir la différence entre:

>>> subprocess.check_output('date | grep 1') 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "/usr/lib/python3.4/subprocess.py", line 603, in check_output 
    with Popen(*popenargs, stdout=PIPE, **kwargs) as process: 
    File "/usr/lib/python3.4/subprocess.py", line 848, in __init__ 
    restore_signals, start_new_session) 
    File "/usr/lib/python3.4/subprocess.py", line 1446, in _execute_child 
    raise child_exception_type(errno_num, err_msg) 
FileNotFoundError: [Errno 2] No such file or directory: 'date | grep 1' 

Et:

>>> subprocess.check_output('date | grep 1', shell=True) 
b'gio 19 giu 2014, 14.15.35, CEST\n' 

Lisez la documentation sur le Frequently Used Arguments pour plus d'informations sur l'argument shell et comment il change l'interprétation des autres arguments.


Notez que vous devriez essayer d'éviter d'utiliser shell=True car créer un shell peut être un danger pour la sécurité (même si vous ne pas exécuter des attaques d'entrée comme non fiables Shellshock peut être réalisée! Encore).

La documentation du module de sous-processus comporte une petite section sur replacing the shell pipeline. Vous pouvez le faire en fraie les deux processus en python et utiliser subprocess.PIPE:

date_proc = subprocess.Popen(['date'], stdout=subprocess.PIPE) 
grep_proc = subprocess.check(['grep', '1'], stdin=date_proc.stdout, stdout=subprocess.PIPE) 
date_proc.stdout.close() 
output = grep_proc.communicate()[0] 

Vous pouvez écrire une fonction wrapper simple de définir facilement les pipelines:

import subprocess 
from shlex import split 
from collections import namedtuple 
from functools import reduce 

proc_output = namedtuple('proc_output', 'stdout stderr') 


def pipeline(starter_command, *commands): 
    if not commands: 
     try: 
      starter_command, *commands = starter_command.split('|') 
     except AttributeError: 
      pass 
    starter_command = _parse(starter_command) 
    starter = subprocess.Popen(starter_command, stdout=subprocess.PIPE) 
    last_proc = reduce(_create_pipe, map(_parse, commands), starter) 
    return proc_output(*last_proc.communicate()) 

def _create_pipe(previous, command): 
    proc = subprocess.Popen(command, stdin=previous.stdout, stdout=subprocess.PIPE) 
    previous.stdout.close() 
    return proc 

def _parse(cmd): 
    try: 
     return split(cmd) 
    except Exception: 
     return cmd 

Avec cela en place, vous pouvez écrire:

pipeline('date | grep 1') 

Ou:

pipeline('date', 'grep 1') 

Ou:

pipeline(['date'], ['grep', '1']) 
+0

Merci qui a fonctionné. – h4ck3d

+0

Juste pour info, certaines implémentations (éventuellement des versions?) Ne déclenchent pas un "FileNotFoundError", mais un "OS Error" sans aucune information utile, tout comme il l'a collé. "C'est pourquoi il" a supprimé les informations essentielles " – Keozon

+0

" Attention: Passing shell = True peut être un danger pour la sécurité s'il est combiné avec une entrée non fiable Voir l'avertissement sous Arguments fréquemment utilisés pour plus de détails. " - https://docs.python.org/2/library/subprocess.html#popen-constructor – Jivan

Questions connexes