527 votes

Exécution de commandes Bash en Python

Sur ma machine locale, j'exécute un python script qui contient cette ligne

bashCommand = "cwm --rdf test.rdf --ntriples > test.nt"
os.system(bashCommand)

Cela fonctionne bien.

J'exécute ensuite le même code sur un serveur et j'obtiens le message d'erreur suivant

'import site' failed; use -v for traceback
Traceback (most recent call last):
File "/usr/bin/cwm", line 48, in <module>
from swap import  diag
ImportError: No module named swap

Donc ce que j'ai fait ensuite, c'est que j'ai inséré un print bashCommand qui m'imprime que la commande dans le terminal avant de l'exécuter avec os.system() .

Bien sûr, je reçois à nouveau l'erreur (causée par os.system(bashCommand) ) mais avant cette erreur, il imprime la commande dans le terminal. Ensuite, j'ai simplement copié cette sortie et fait un copier-coller dans le terminal, puis j'ai appuyé sur Entrée et ça marche...

Est-ce que quelqu'un a une idée de ce qui se passe ?

3 votes

Il semble y avoir une différence dans l'environnement selon la façon dont vous exécutez cwm . Peut-être avez-vous une certaine configuration dans votre .bashrc qui configure l'environnement pour une utilisation interactive de bash ?

0 votes

Avez-vous essayé d'exécuter la commande à partir de la ligne de commande lorsque vous êtes connecté au serveur ? Votre message indique simplement que vous l'avez "collée dans le terminal".

0 votes

@Sven : oui, je voulais dire que j'ai exécuté la commande directement dans le terminal du serveur.

9voto

ricardo130 Points 137

Vous pouvez également utiliser 'os.popen'. Exemple :

import os

command = os.popen('ls -al')
print(command.read())
print(command.close())

Sortie :

total 16
drwxr-xr-x 2 root root 4096 ago 13 21:53 .
drwxr-xr-x 4 root root 4096 ago 13 01:50 ..
-rw-r--r-- 1 root root 1278 ago 13 21:12 bot.py
-rw-r--r-- 1 root root   77 ago 13 21:53 test.py

None

8voto

kichik Points 7249

Selon l'erreur, il vous manque un paquet nommé swap sur le serveur. Ce site /usr/bin/cwm l'exige. Si vous êtes sur Ubuntu/Debian, installez python-swap en utilisant l'aptitude.

0 votes

Mais ça marche quand je l'exécute directement dans le terminal... donc le swap doit être là, non ?

0 votes

Il y a deux options. Soit il ne peut pas trouver swap ou il n'aurait pas dû l'importer en premier lieu. pouvez-vous import swap manuellement ? cela fonctionne-t-il ?

0 votes

Hm je ne peux pas. Si je lance python en tapant python dans le terminal et que je tape import swap, j'obtiens l'erreur "ImportError : No module named swap". Ce qui est bizarre, c'est que cela fonctionne quand je lance la commande cwm directement dans le terminal du serveur.

7voto

J.F. Sebastian Points 102961

Pour exécuter la commande sans shell, passez la commande en tant que liste et implémenter la redirection en Python en utilisant [subprocess] :

#!/usr/bin/env python
import subprocess

with open('test.nt', 'wb', 0) as file:
    subprocess.check_call("cwm --rdf test.rdf --ntriples".split(),
                          stdout=file)

Note : pas de > test.nt à la fin. stdout=file met en œuvre la redirection.


Pour exécuter la commande à l'aide de l'interpréteur de commandes en Python, passez la commande en tant qu'objet chaîne de caractères et permettre shell=True :

#!/usr/bin/env python
import subprocess

subprocess.check_call("cwm --rdf test.rdf --ntriples > test.nt",
                      shell=True)

Voici le shell responsable de la redirection de la sortie ( > test.nt est dans la commande).


Pour lancer une commande bash qui utilise des bashismes, spécifiez explicitement l'exécutable bash ; par exemple, pour émuler la substitution du processus bash :

#!/usr/bin/env python
import subprocess

subprocess.check_call('program <(command) <(another-command)',
                      shell=True, executable='/bin/bash')

1voto

RewordedAnswers Points 19

La façon pythonique de faire cela est d'utiliser subprocess.Popen

subprocess.Popen prend une liste dont le premier élément est la commande à exécuter, suivie de tout argument de ligne de commande.

A titre d'exemple :

import subprocess

args = ['echo', 'Hello!']
subprocess.Popen(args) // same as running `echo Hello!` on cmd line

args2 = ['echo', '-v', '"Hello Again"']
subprocess.Popen(args2) // same as running 'echo -v "Hello Again!"` on cmd line

1voto

dux2 Points 181

subprocess.Popen() est préférée à os.system() car il offre plus de contrôle et de visibilité. Cependant, si vous trouvez subprocess.Popen() trop verbeux ou trop complexe, peasyshell est un petit wrapper que j'ai écrit au-dessus, qui permet d'interagir facilement avec bash depuis Python.

https://github.com/davidohana/peasyshell

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