Question

J'ai un commandement comme celui-ci.

wmctrl -lp | awk '/gedit/ { print $1 }'

Et je veux sa sortie dans un script python, j'ai essayé ce code

>>> import subprocess
>>> proc =  subprocess.Popen(["wmctrl -lp", "|","awk '/gedit/ {print $1}"], shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
>>> proc.stdout.readline()
'0x0160001b -1 6504   beer-laptop x-nautilus-desktop\n'
>>> proc.stdout.readline()
'0x0352f117  0 6963   beer-laptop How to get output from external command combine with Pipe - Stack Overflow - Chromium\n'
>>> proc.stdout.readline()
'0x01400003 -1 6503   beer-laptop Bottom Expanded Edge Panel\n'
>>> 

Il semble que mon code soit incorrect, seul wmctrl -lp a été exécuté et | awk '{print $ 1}' est omis Ma sortie attendue voudrait que 0x03800081

$ wmctrl -lp | awk '/gedit/ {print $1}'
0x03800081

Est-ce que quelqu'un aide s'il vous plaît.

Était-ce utile?

La solution

Avec shell = True , vous devez utiliser une seule ligne de commande au lieu d'un tableau, sinon vos arguments supplémentaires sont interprétés comme des arguments shell. Dans la documentation sur le sous-processus :

  

Sous Unix, avec shell = True: Si args est une chaîne, il spécifie la chaîne de commande à exécuter via le shell. Si args est une séquence, le premier élément spécifie la chaîne de commande et tous les éléments supplémentaires seront traités comme des arguments de shell supplémentaires.

Votre appel devrait donc être:

subprocess.Popen("wmctrl -lp | sed /gedit/ '{print $1}'", shell=True, ...

Je pense que vous pouvez également avoir une citation simple non équilibrée.

Autres conseils

Etant donné que vous transmettez une séquence au programme, il pense que le canal est un argument à wmcrtrl , comme si vous l'aviez fait

.
wmctrl -lp "|"

et ainsi l'opération de conduite réelle est perdue.

En faire une chaîne unique devrait en effet vous donner le bon résultat:

>>> import subprocess as s
>>> proc = s.Popen("echo hello | grep e", shell=True, stdout=s.PIPE, stderr=s.PIPE)
>>> proc.stdout.readline()
'hello\n'
>>> proc.stdout.readline()
''

Après quelques recherches, j'ai le code suivant qui fonctionne très bien pour moi. Il imprime essentiellement stdout et stderr en temps réel. J'espère que cela aidera quelqu'un d'autre qui en a besoin.

stdout_result = 1
stderr_result = 1


def stdout_thread(pipe):
    global stdout_result
    while True:
        out = pipe.stdout.read(1)
        stdout_result = pipe.poll()
        if out == '' and stdout_result is not None:
            break

        if out != '':
            sys.stdout.write(out)
            sys.stdout.flush()


def stderr_thread(pipe):
    global stderr_result
    while True:
        err = pipe.stderr.read(1)
        stderr_result = pipe.poll()
        if err == '' and stderr_result is not None:
            break

        if err != '':
            sys.stdout.write(err)
            sys.stdout.flush()


def exec_command(command, cwd=None):
    if cwd is not None:
        print '[' + ' '.join(command) + '] in ' + cwd
    else:
        print '[' + ' '.join(command) + ']'

    p = subprocess.Popen(
        command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=cwd
    )

    out_thread = threading.Thread(name='stdout_thread', target=stdout_thread, args=(p,))
    err_thread = threading.Thread(name='stderr_thread', target=stderr_thread, args=(p,))

    err_thread.start()
    out_thread.start()

    out_thread.join()
    err_thread.join()

    return stdout_result + stderr_result

Lorsque cela est nécessaire, je pense qu'il est facile de collecter la sortie ou l'erreur dans une chaîne et de la retourner.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top