Python 在远程 shell 中使用 Fabric 进行 run() 调用时,我可以捕获错误代码吗?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4888568/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-18 17:59:40  来源:igfitidea点击:

Can I catch error codes when using Fabric to run() calls in a remote shell?

pythonerror-handlingfabric

提问by Alan Plum

Normally Fabric quits as soon as a run() call returns a non-zero exit code. For some calls, however, this is expected. For example, PNGOut returns an error code of 2 when it is unable to compress a file.

通常,只要 run() 调用返回非零退出代码,Fabric 就会退出。但是,对于某些呼叫,这是意料之中的。例如,PNGOut 在无法压缩文件时返回错误代码 2。

Currently I can only circumvent this limitation by either using shell logic (do_something_that_fails || trueor do_something_that_fails || do_something_else), but I'd rather be able to keep my logic in plain Python (as is the Fabric promise).

目前,我只能通过使用 shell 逻辑(do_something_that_fails || truedo_something_that_fails || do_something_else)来规避此限制,但我更愿意将我的逻辑保留在纯 Python 中(就像 Fabric 承诺一样)。

Is there a way to check for an error code and react to it rather than having Fabric panic and die? I still want the default behaviours for other calls, so changing its behaviour by modifying the environment doesn't seem like a good option (and as far as I recall, you can only use that to tell it to warn instead of dying anyway).

有没有办法检查错误代码并对其做出反应,而不是让 Fabric 恐慌和死亡?我仍然想要其他调用的默认行为,所以通过修改环境来改变它的行为似乎不是一个好的选择(据我所知,你只能用它来告诉它警告而不是死)。

采纳答案by akaihola

You can prevent aborting on non-zero exit codes by using the settingscontext manager and the warn_onlysetting:

您可以使用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()

Update:My answer is outdated. See comments below.

更新:我的答案已过时。请参阅下面的评论。

回答by Alan Plum

Apparently messing with the environment isthe answer.

显然,弄乱环境就是答案。

fabric.api.settingscan be used as a context manager (with with) to apply it to individual statements. The return value of run(), local()and sudo()calls isn't just the output of the shell command, but also has special properties (return_codeand failed) that allow reacting to the errors.

fabric.api.settings可以用作上下文管理器(带有with)以将其应用于单个语句。run(), local()andsudo()调用的返回值不仅是shell 命令的输出,还具有允许对错误做出反应的特殊属性(return_codefailed)。

I guess I was looking for something closer to the behaviour of subprocess.Popenor Python's usual exception handling.

我想我正在寻找更接近subprocess.PopenPython 的通常异常处理行为的东西。

回答by ArtOfWarfare

Yes, you can. Just change the environment's abort_exception. For example:

是的你可以。只要改变环境的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>

The documentation on abort_exceptionis here.

上的文档abort_exceptionhere

回答by Yahya Yahyaoui

try this

尝试这个

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