3

我一直在试图弄清楚当我的结构脚本失败时最好的方法是什么(例如通过 python 模块发送一条松弛通知消息slackbot)。

我做了一个例子,我在这里尝试执行上述操作:

fab_failtest.py my_slackclient.py

您可以通过将两个文件下载到目录 pip installfabric和来运行上面的示例slackbot,然后运行:

fab --fabfile=fab_failtest.py fail_test1 或者

fab --fabfile=fab_failtest.py fail_test2

(你还必须有一台可以通过 ssh 连接的机器,在这个例子中我mrbluesky@elo打开了 ssh 端口22

  • fail_test1使用try-except所以我可以获得异常错误信息等等
  • fail_test2使用try-finally加上一个简单的布尔变量,因此没有异常信息可用

起初我以为我有这个fail_test1例子,但我已经看到它失败了好几次发送失败的松弛消息,我想知道是否可能存在竞争条件或涉及什么?我可以开始使用fail_test2,但我真的很喜欢像 in 一样访问堆栈跟踪fail_test1

有没有更好的方法来做到这一点,比如在 python 结构中提供的东西可以完全完成我在上面的例子中想要完成的事情?

4

1 回答 1

2

我不同意你的两种方法。我坚信代码越少越好。我是什么意思?一个函数应该像它的名字所说的那样做,不多不少,如果你必须添加一个全局处理程序,我会把它作为一个包装器添加,结构函数很难阅读,不需要添加错误处理到混合。照这样说:

import sys
import traceback

from fabric.api import task, settings, local, abort
from fabric.decorators import _wrap_as_new
from functools import wraps

HOST = 'elo'
PORT = 22


def alert_on_fail(func):
    @wraps(func)
    def decorated(*args, **kwargs):
        try:
            return func(*args, **kwargs)
        except:
            # TODO: add more code here
            exception_type, value, tb_msg = sys.exc_info()
            traceback_msg = traceback.format_exc()
            notify('something went wrong: ' + traceback_msg)
            abort('exiting error!!')
    return _wrap_as_new(func, decorated)


@task
@alert_on_fail
def fail_test(host=HOST, port=PORT):
    notify('fail test', msg_type='info')
    local('''python -c "raise Exception('foobar')"''')
    notify('script ran successfully', msg_type='success')  # this will never run because the function above crashed


@task
@alert_on_fail
def pass_test(host=HOST, port=PORT):
    notify('pass test', msg_type='info')
    local('whoami')
    notify('script ran successfully', msg_type='success')


def notify(msg, **kwargs):
    # DISREGARD THIS
    print 'sent to slack:', msg

输出:

$ fab fail_test
sent to slack: fail test
[localhost] local: python -c "raise Exception('foobar')"
Traceback (most recent call last):
  File "<string>", line 1, in <module>
Exception: foobar

Fatal error: local() encountered an error (return code 1) while executing 'python -c "raise Exception('foobar')"'

Aborting.
sent to slack: something went wrong: Traceback (most recent call last):
  File "/private/tmp/fabfile.py", line 21, in decorated
    return func(*args, **kwargs)
  File "/private/tmp/fabfile.py", line 34, in fail_test
    local('''python -c "raise Exception('foobar')"''')
  File "/usr/local/lib/python2.7/site-packages/fabric/operations.py", line 1198, in local
    error(message=msg, stdout=out, stderr=err)
  File "/usr/local/lib/python2.7/site-packages/fabric/utils.py", line 347, in error
    return func(message)
  File "/usr/local/lib/python2.7/site-packages/fabric/utils.py", line 53, in abort
    sys.exit(msg)
SystemExit: local() encountered an error (return code 1) while executing 'python -c "raise Exception('foobar')"'


Fatal error: exiting error!!

Aborting.
exiting error!!

和:

$ fab pass_test
sent to slack: pass test
[localhost] local: whoami
buzzi
sent to slack: script ran successfully

Done.

您会注意到这些函数现在“易于”阅读,它们“简单”,所有错误处理代码都已移至其他地方。

于 2015-11-18T16:07:28.523 回答