3

ファブリック スクリプトが失敗したときに何かを行う最善の方法を見つけようとしています (たとえば、 python module を介して Slack 通知メッセージを送信しますslackbot)。

ここで上記を実行しようとする例を作成しました。

fab_failtest.py my_slackclient.py

上記の例を実行するには、両方のファイルをディレクトリにダウンロードし、 pip installfabricslackbotを実行します。

fab --fabfile=fab_failtest.py fail_test1 また

fab --fabfile=fab_failtest.py fail_test2

(sshできるマシンも必要です。この例ではmrbluesky@elo、開いているsshポートをオンにしています22

  • fail_test1を使用しtry-exceptて、例外エラー情報などを取得できます
  • fail_test2try-finallyプラスの単純なブール変数を使用するため、例外情報は利用できません

最初は例でそれを持っていると思っていましたfail_test1が、失敗時にスラックメッセージを送信するのに何度か失敗したのを見てきました.競合状態や何かが関係しているのではないかと思っています. fail_test2代わりに使用を開始することもできますが、のようにスタック トレースにアクセスしたいの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 に答える