web-dev-qa-db-fra.com

Supprimer la sortie dans Python appels aux exécutables

J'ai un binaire nommé A qui génère une sortie lorsqu'il est appelé. Si je l'appelle depuis un Bash Shell, la plupart de la sortie est supprimée par A > /dev/null. Toute la sortie est supprimée par A &> /dev/null

J'ai un script python nommé B qui doit appeler A. Je veux pouvoir générer une sortie à partir de B, tout en supprimant toutes les sorties de A.

Depuis B, j'ai essayé os.system('A'), os.system('A > /dev/null') et os.system('A &> /dev/null'), os.execvp('...'), etc. mais aucun de ceux-ci suppriment toute la sortie de A.

Je pourrais exécuter B &> /dev/null, Mais cela supprime également toutes les sorties de B et je ne le veux pas.

Quelqu'un a des suggestions?

44
Lin

Si vous avez Python 2.4, vous pouvez utiliser le module de sous-processus :

>>> import subprocess
>>> s = subprocess.Popen(['cowsay', 'hello'], \
      stderr=subprocess.STDOUT, stdout=subprocess.PIPE).communicate()[0]
>>> print s
 _______ 
< hello >
 ------- 
        \   ^__^
         \  (oo)\_______
            (__)\       )\/\
                ||----w |
                ||     ||
57
Manuel
import os
import subprocess

command = ["executable", "argument_1", "argument_2"]

with open(os.devnull, "w") as fnull:
    result = subprocess.call(command, stdout = fnull, stderr = fnull)

Si la commande n'a pas d'arguments, vous pouvez simplement la fournir sous forme de chaîne simple.

Si votre commande s'appuie sur des fonctionnalités Shell telles que les caractères génériques, les canaux ou les variables d'environnement, vous devrez fournir la commande entière sous forme de chaîne et également spécifier Shell = True. Cela doit être évité, car il représente un risque pour la sécurité si le contenu de la chaîne n'est pas soigneusement validé.

102
DNS

Dans Python 3.3 et supérieur, subprocess prend en charge ne option pour rediriger vers /dev/null . Pour l'utiliser, lors de l'appel de .Popen Et amis, spécifiez stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, Comme arguments de mot-clé.

La réponse de DNS, réécrite pour Python 3.3+, devient

import subprocess
command = ["executable", "argument_1", "argument_2"]
result = subprocess.call(command,
                         stdout=subprocess.DEVNULL,
                         stderr=subprocess.DEVNULL)

De la documentation:

subprocess.DEVNULL¶

Valeur spéciale qui peut être utilisée comme argument stdin, stdout ou stderr pour Popen et indique que le fichier spécial os.devnull sera utilisé.

Nouveau dans la version 3.3.

Pour Python 3.0 à 3.2, vous devez ouvrir manuellement le périphérique nul à l'aide de open(os.devnull), comme DNS l'a écrit.

21
Mechanical snail

Si votre moteur de recherche vous amène à cette vieille question (comme moi), sachez que l'utilisation de PIPE peut conduire à deadlocks. En effet, les tubes étant tamponnés, vous pouvez écrire un certain nombre d'octets dans un tube, même si personne ne le lit. Cependant, la taille du tampon est finie. Et par conséquent, si votre programme A a une sortie supérieure à la mémoire tampon, A sera bloqué lors de l'écriture, tandis que le programme appelant B attend la fin de A. Mais pas, dans ce cas particulier ... voir les commentaires ci-dessous.

Pourtant, je recommande d'utiliser Devin Jeanpierre et la solution DNS.

12
Po' Lazarus

Comme le mentionnent les documents os.system (), utilisez le module subprocess et, si vous le souhaitez, définissez stdout = open (os.devnull, 'w') (et peut-être la même chose pour stderr) lorsque vous ouvrez le sous-processus.

8
Devin Jeanpierre

Je sais qu'il est tard dans le jeu, mais pourquoi ne pas simplement rediriger la sortie vers/dev/null depuis os.system? Par exemple.:

tgt_file = "./bogus.txt"
os.sytem("d2u '%s' &> /dev/null" % tgt_file)

Cela semble fonctionner pour les occasions où vous ne voulez pas traiter avec subprocess.STDOUT.

1
Rob Carr

J'utilise:

call(command, stderr=subprocess.PIPE, stdout=subprocess.PIPE)

où commande est la chaîne de la commande + arguments

Pour que cela fonctionne, vous devez importer un sous-processus

0
TTT

Si vous avez juste besoin de capturer STDOUT, ne l'attribuez-vous pas à une variable? Par exemple:

megabyte=''
# Create a 1 MiB string of NULL characters.
for i in range(1048576):
    megabyte += '\0'
fh=open('zero.bin','w')
# Write an 8 GiB file.
for i in range(8192):
    print(i)
    # Suppress output of 'write()' by assigning to a variable.
    discard=fh.write(megabyte)
fh.close()

Je créais un grand fichier rempli de zéro pour libérer de l'espace libre sur mon disque dur et j'ai découvert que chaque appel à handle.write (chaîne) crache le nombre d'octets écrits. L'affecter à une variable supprimait cette sortie.

0
ECJB

Si vous ne souhaitez pas attendre la fin de la commande, comme le démarrage d'une tâche de sauvegarde, une autre option consiste à la passer par bash, ce qui permet à la redirection de fonctionner normalement.

Par exemple, démarrer un fichier son en utilisant aplay:

import os

def PlaySound(filename):
    command = 'bash -c "aplay %s &> /dev/null &"' % (filename)
    os.system(command)

De cette façon, je peux générer un nouveau processus, sans attendre qu'il se termine et l'empêcher d'imprimer sur le terminal. Le seul hic, c'est qu'il chargera une instance bash ainsi que le processus que vous exécutez, fournissant un léger surcoût.

0
PiBorg