web-dev-qa-db-fra.com

Puis-je intercepter des codes d'erreur lors de l'utilisation de Fabric pour exécuter des appels () dans un shell distant?

Normalement, Fabric se ferme dès qu'un appel run () renvoie un code de sortie différent de zéro. Cependant, pour certains appels, cela est prévu. Par exemple, PNGOut renvoie un code d'erreur de 2 lorsqu'il ne parvient pas à compresser un fichier.

Actuellement, je ne peux contourner cette limitation qu'en utilisant la logique Shell (do_something_that_fails || true ou do_something_that_fails || do_something_else), mais je préférerais pouvoir garder ma logique en clair Python (comme c'est la promesse de Fabric).

Existe-t-il un moyen de rechercher un code d'erreur et d'y réagir plutôt que de paniquer Fabric et de mourir? Je veux toujours les comportements par défaut pour les autres appels, donc changer son comportement en modifiant l'environnement ne semble pas être une bonne option (et pour autant que je m'en souvienne, vous ne pouvez l'utiliser que pour lui dire d'avertir au lieu de mourir de toute façon).

64
Alan Plum

Vous pouvez empêcher l'annulation de codes de sortie différents de zéro en utilisant le gestionnaire de contexte settings et le warn_only réglage:

from fabric.api import settings

with settings(warn_only=True):
    result = run('pngout old.png new.png')
    if result.return_code == 0: 
        do something
    Elif result.return_code == 2: 
        do something else 
    else: #print error to user
        print result
        raise SystemExit()

Mise à jour: Ma réponse est obsolète. Voir les commentaires ci-dessous.

90
akaihola

Oui, vous pouvez. Il suffit de changer l'environnement abort_exception. Par exemple:

from fabric.api import settings

class FabricException(Exception):
    pass

with settings(abort_exception = FabricException):
    try:
        run(<something that might fail>)
    except FabricException:
        <handle the exception>

La documentation sur abort_exception est ici .

29
ArtOfWarfare

Apparemment jouer avec l'environnement est la réponse.

fabric.api.settings Peut être utilisé comme gestionnaire de contexte (avec with) pour l'appliquer à des instructions individuelles. La valeur de retour des appels run(), local() et Sudo() n'est pas seulement la sortie de la commande Shell, mais possède également des propriétés spéciales (return_code et failed) qui permettent de réagir aux erreurs.

Je suppose que je cherchais quelque chose de plus proche du comportement de subprocess.Popen Ou de la gestion des exceptions habituelle de Python.

4
Alan Plum

essaye ça

from fabric.api import run, env
env.warn_only = True # if you want to ignore exceptions and handle them yurself

command = "your command"
x = run(command, capture=True) # run or local or Sudo
if(x.stderr != ""):
    error = "On %s: %s" %(command, x.stderr)
    print error
    print x.return_code # which may be 1 or 2
    # do what you want or
    raise Exception(error) #optional
else:
    print "the output of %s is: %s" %(command, x)
    print x.return_code # which is 0
2
Yahya Yahyaoui