Могу ли я улавливать коды ошибок при использовании вызовов Fabric для запуска() в удаленной оболочке?

Обычно Fabric завершает работу, как только вызов run() возвращает ненулевой код выхода. Однако для некоторых вызовов это ожидается. Например, PNGOut возвращает код ошибки 2, когда он не может сжать файл.

В настоящее время я могу обойти это ограничение только с помощью shell-логики (do_something_that_fails || true или do_something_that_fails || do_something_else), но я предпочел бы сохранить свою логику на простом Python (как и обещание Fabric).

Есть ли способ проверить код ошибки и отреагировать на него, а не наложить панику и умереть? Я по-прежнему хочу поведения по умолчанию для других вызовов, поэтому изменение его поведения путем изменения среды не похоже на хороший вариант (и, насколько я помню, вы можете использовать это только для того, чтобы предупредить его, а не умереть в любом случае).

Ответ 1

Вы можете предотвратить прерывание при ненулевых кодах выхода с помощью диспетчера контекстов settings и параметра warn_only:

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()

Обновление: Мой ответ устарел. См. Комментарии ниже.

Ответ 2

Да, вы можете. Просто измените среду abort_exception. Например:

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>

Документация на abort_exception здесь.

Ответ 3

По-видимому, беспорядок в среде - это ответ.

fabric.api.settings может использоваться как менеджер контекста (с with), чтобы применить его к отдельным операторам. Возвращаемое значение вызовов run(), local() и sudo() является не только результатом команды оболочки, но также имеет специальные свойства (return_code и failed), которые позволяют реагировать на ошибки.

Я предполагаю, что я искал что-то более близкое к поведению subprocess.Popen или обычной обработки исключений Python.

Ответ 4

попробуйте это

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