92 votes

Vérifier si un programme existe à partir d'un script python.

Comment vérifier si un programme existe à partir d'un script python ?

Disons que vous voulez vérifier si wget o curl sont disponibles. Nous supposerons qu'ils doivent être dans le chemin.

Le mieux serait de voir une solution multiplateforme mais pour l'instant, Linux suffit.

Des conseils :

  • exécuter la commande et vérifier le code de retour n'est pas toujours suffisant car certains outils renvoient un résultat différent de 0 même lorsque vous essayez --version .
  • rien ne doit être visible à l'écran lors de la vérification de la commande

De plus, j'apprécierais une solution plus générale, du genre is_tool(name)

11voto

Daren Thomas Points 26812

Je débourserais probablement pour which wget o which curl et vérifiez que le résultat se termine par le nom du programme que vous utilisez. La magie d'unix :)

En fait, il suffit de vérifier le code de retour de la fonction which . Donc... en utilisant notre fidèle subprocess module :

import subprocess

rc = subprocess.call(['which', 'wget'])
if rc == 0:
    print 'wget installed!'
else:
    print 'wget missing in path!'

Notez que j'ai testé ceci sous Windows avec cygwin... Si vous voulez savoir comment implémenter which en pur python, je vous suggère de vérifier ici : http://pypi.python.org/pypi/pycoreutils (Oh, mon Dieu, il semble qu'ils ne fournissent pas ) which . Il est temps de donner un coup de pouce amical)

UPDATE : Sous Windows, vous pouvez utiliser where au lieu de which pour un effet similaire.

5voto

Nicole Finnie Points 941

Je modifierais la réponse de @sorin comme suit, la raison étant que cela vérifierait le nom du programme sans passer par le chemin absolu du programme

from subprocess import Popen, PIPE

def check_program_exists(name):
    p = Popen(['/usr/bin/which', name], stdout=PIPE, stderr=PIPE)
    p.communicate()
    return p.returncode == 0

1voto

ryanday Points 1367
import os
import subprocess

def is_tool(prog):
    for dir in os.environ['PATH'].split(os.pathsep):
        if os.path.exists(os.path.join(dir, prog)):
            try:
                subprocess.call([os.path.join(dir, prog)],
                                stdout=subprocess.PIPE,
                                stderr=subprocess.STDOUT)
            except OSError, e:
                return False
            return True
    return False

0voto

Chris Simpkins Points 101

Une légère modification du code de @SvenMarnach qui résout le problème de l'impression sur le flux de sortie standard. Si vous utilisez la fonction subprocess.check_output() plutôt que la fonction subprocess.call() vous pouvez alors traiter la chaîne qui est normalement imprimée en standard dans votre code et continuer à attraper les exceptions et le code d'état de sortie.

Si vous voulez supprimer le flux de sortie standard dans le terminal, n'imprimez pas la chaîne std out qui est retournée par la commande check_output :

import subprocess
import os
try:
    stdout_string = subprocess.check_output(["wget", "--help"], stderr=subprocess.STDOUT)
    # print(stdout_string)
except subprocess.CalledProcessError as cpe:
    print(cpe.returncode)
    print(cpe.output)
except OSError as e:
    if e.errno == os.errno.ENOENT:
        print(e)
    else:
        # Something else went wrong while trying to run `wget`
        print(e)

Le code d'état de sortie non nul et la chaîne de sortie sont affichés dans la fenêtre de l'utilisateur. CalledProcessError comme subprocess.CalledProcessError.returncode y subprocess.CalledProcessError.output donc vous pouvez faire ce que vous voulez avec eux.

Si vous voulez imprimer la sortie standard de l'exécutable dans le terminal, imprimez la chaîne qui est retournée :

import subprocess
import os
try:
    stdout_string = subprocess.check_output(["wget", "--help"], stderr=subprocess.STDOUT)
    print(stdout_string)
except subprocess.CalledProcessError as cpe:
    print(cpe.returncode)
    print(cpe.output)
except OSError as e:
    if e.errno == os.errno.ENOENT:
        print(e)
    else:
        # Something else went wrong while trying to run `wget`
        print(e)

print() ajoute une nouvelle ligne à la chaîne. Si vous voulez éliminer cela (et écrire l'erreur std dans le flux std err au lieu du flux std out comme indiqué avec les instructions print() ci-dessus), utilisez sys.stdout.write(string) y sys.stderr.write(string) au lieu de print() :

import subprocess
import os
import sys
try:
    stdout_string = subprocess.check_output(["bogus"], stderr=subprocess.STDOUT)
    sys.stdout.write(stdout_string)
except subprocess.CalledProcessError as cpe:
    sys.stderr.write(cpe.returncode)
    sys.stderr.write(cpe.output)
except OSError as e:
    if e.errno == os.errno.ENOENT:
        sys.stderr.write(e.strerror)
    else:
        # Something else went wrong while trying to run `wget`
        sys.stderr.write(e.strerror)

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