87 votes

Equivalent des backticks de Bash en Python

Quel est l'équivalent en Python des backticks que l'on trouve en Ruby et Perl ? C'est-à-dire qu'en Ruby, je peux faire ceci :

foo = `cat /tmp/baz`

À quoi ressemble l'instruction équivalente en Python ? J'ai essayé os.system("cat /tmp/baz") mais qui met le résultat en sortie standard et me renvoie le code d'erreur de cette opération.

0 votes

104voto

John Kugelman Points 108754
output = os.popen('cat /tmp/baz').read()

4 votes

@mckenzm La question porte sur la capture de la sortie d'un processus externe. Capturer la sortie d'une fonction Python serait une question bien différente.

1 votes

Merveilleusement concis, et en fait l'équivalent de l'outil Ruby `...` (capture de stdout, passage de stderr) - avec une exception : Ruby permet de déterminer le code de sortie du processus via $? après coup ; en Python, d'après ce que je peux dire, vous devrez utiliser la fonction subprocess Les fonctions du module pour cela.

83voto

sth Points 91594

La méthode la plus souple consiste à utiliser l'option subprocess module :

import subprocess

out = subprocess.run(["cat", "/tmp/baz"], capture_output=True)
print("program output:", out)

capture_output a été introduite dans Python 3.7. Pour les versions antérieures, la fonction spéciale check_output() peut être utilisé à la place :

out = subprocess.check_output(["cat", "/tmp/baz"])

Vous pouvez également construire manuellement un objet sous-processus si vous avez besoin d'un contrôle plus fin :

proc = subprocess.Popen(["cat", "/tmp/baz"], stdout=subprocess.PIPE)
(out, err) = proc.communicate()

Toutes ces fonctions permettent paramètres des mots-clés pour personnaliser la façon dont le sous-processus est exécuté. Vous pouvez par exemple utiliser shell=True pour exécuter le programme par l'intermédiaire de l'interpréteur de commandes, si vous avez besoin de choses comme des expansions de nom de fichier de * mais cela vient avec limitations .

2 votes

Oui, c'est la seule façon saine, vous pourriez l'envelopper dans une fonction pour pouvoir appeler quelque chose comme execute("command")

0 votes

En fait, cela ne fonctionne pas pour moi, car dans ce cas, baz est un répertoire et j'essaie d'obtenir le contenu de tous les fichiers de ce répertoire. (faire cat /tmp/baz/* fonctionne en ticks mais pas via la méthode décrite ici)

6 votes

Re : "*" ne fonctionne pas ; utilisez subprocess.Popen(["cat", "/tmp/baz"], stdout=subprocess.PIPE, shell=True) à la place. Puisque l'expansion glob (étoile) est gérée par l'interpréteur de commandes, le module de sous-processus doit utiliser l'expansion de l'interpréteur de commandes dans ce cas (fournie par /bin/sh).

28voto

bobince Points 270740

qqch est correct . Vous pouvez également utiliser os.popen(), mais lorsqu'il est disponible (Python 2.4+), le sous-processus est généralement préférable.

Cependant, contrairement à certains langages qui l'encouragent, il est généralement considéré comme une mauvaise pratique de créer un sous-processus dans lequel vous pouvez effectuer le même travail à l'intérieur du langage. C'est plus lent, moins fiable et dépendant de la plate-forme. Votre exemple serait plus approprié en tant que :

foo= open('/tmp/baz').read()

eta :

baz est un répertoire et j'essaie d'obtenir le contenu de tous les fichiers de ce répertoire.

? cat sur un répertoire me donne une erreur.

Si vous voulez une liste de fichiers :

import os
foo= os.listdir('/tmp/baz')

Si vous voulez le contenu de tous les fichiers d'un répertoire, quelque chose comme :

contents= []
for leaf in os.listdir('/tmp/baz'):
    path= os.path.join('/tmp/baz', leaf)
    if os.path.isfile(path):
        contents.append(open(path, 'rb').read())
foo= ''.join(contents)

ou, si vous pouvez être sûr qu'il n'y a pas de répertoires là-dedans, vous pouvez le faire tenir en une seule ligne :

path= '/tmp/baz'
foo= ''.join(open(os.path.join(path, child), 'rb').read() for child in os.listdir(path))

1 votes

Bien que ce ne soit pas une réponse à la question, c'est la meilleure réponse pour éduquer les utilisateurs.

1 votes

Le titre de la question est "quel est l'équivalent des backticks". J'ai supposé que "cat" était juste une commande d'exemple. Cette réponse n'est d'aucune utilité dans le cas général.

16voto

J.F. Sebastian Points 102961
foo = subprocess.check_output(["cat", "/tmp/baz"])

3 votes

C'est le moyen le plus simple à présent. "subprocess.check_output" a été ajouté dans Python 2.7, qui a été publié en juillet 2010, après que les autres réponses "popen" aient été données.

6voto

Le moyen le plus simple est d'utiliser le paquet de commandes.

import commands

commands.getoutput("whoami")

Sortie :

bganesan

6 votes

Très facile, mais le module est maintenant déprécié.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X