22

例外をスローする可能性のある行がたくさんありますが、それでも次の行に続くはずです。例外をスローする可能性のあるすべてのステートメントを個別にキャッチしようとせずにこれを行うにはどうすればよいですか?

try:
    this_may_cause_an_exception()
    but_I_still_wanna_run_this()
    and_this()
    and_also_this()
except Exception, e:
    logging.exception('An error maybe occured in one of first occuring functions causing the others not to be executed. Locals: {locals}'.format(locals=locals()))

上記のコードを見てみましょう。すべての関数が例外をスローする可能性がありますが、例外をスローしたかどうかに関係なく、次の関数を実行する必要があります。それを行う良い方法はありますか?

私はこれをしたくありません:

try:
    this_may_cause_an_exception()
except:
    pass
try:
    but_I_still_wanna_run_this()
except:
    pass
try:
    and_this()
except:
    pass
try:
    and_also_this()
except:
    pass

例外が重大な場合にのみ、例外の後もコードを実行し続ける必要があると思います(コンピューターが燃えるか、システム全体が台無しになり、プログラム全体が停止するはずですが、接続などの多くの小さなことでも例外がスローされます失敗など)通常、例外処理に問題はありませんが、この場合、小さなことで簡単に例外をスローするサードパーティのライブラリを使用しています.

m4spy の回答を見た後、例外が発生した場合でも関数内のすべての行を実行できるようにするデコレータを使用することは不可能だと思いました。

このようなものはクールです:

def silent_log_exceptions(func):
    @wraps(func)
    def _wrapper(*args, **kwargs):
        try:
            func(*args, **kwargs)
        except Exception:
            logging.exception('...')
            some_special_python_keyword # which causes it to continue executing the next line
    return _wrapper

またはこのようなもの:

def silent_log_exceptions(func):
    @wraps(func)
    def _wrapper(*args, **kwargs):
        for line in func(*args, **kwargs):
            try:
                exec line
            except Exception:
                logging.exception('...')
    return _wrapper



@silent_log_exceptions
def save_tweets():
    a = requests.get('http://twitter.com)
    x = parse(a)
    bla = x * x
4

6 に答える 6

25
for func in [this_may_cause_an_exception,
             but_I_still_wanna_run_this,
             and_this,
             and_also_this]:
    try:
        func()
    except:
        pass

ここで注意すべき点が2つあります。

  • 実行するすべてのアクションは、同じシグニチャを持つ呼び出し可能オブジェクト(この例では、引数をとらない呼び出し可能オブジェクト)で表す必要があります。まだの場合は、小さな関数、lambda式、呼び出し可能なクラスなどでラップします。
  • exceptの節は悪い考えですが、おそらくあなたはすでにそれを知っていたでしょう。

より柔軟な別のアプローチは、次のような高階関数を使用することです。

def logging_exceptions(f, *args, **kwargs):
    try:
        f(*args, **kwargs)
    except Exception as e:
        print("Houston, we have a problem: {0}".format(e))
于 2012-06-05T14:09:51.947 に答える
3

私は似たようなことに遭遇し、SO hereについて質問しました。受け入れられた回答は、ログを処理し、特定の例外のみを監視します。私は修正版で終わった:

class Suppressor:
    def __init__(self, exception_type, l=None):
        self._exception_type = exception_type
        self.logger = logging.getLogger('Suppressor')
        if l:
            self.l = l
        else:
            self.l = {}
    def __call__(self, expression):
        try:
            exec expression in self.l
        except self._exception_type as e:
            self.logger.debug('Suppressor: suppressed exception %s with content \'%s\'' % (type(self._exception_type), e))

次のように使用できます。

s = Suppressor(yourError, locals()) 
s(cmdString)

したがって、コマンドのリストを設定しmap、サプレッサーと一緒に使用して、すべてのコマンドを実行できます。

于 2012-06-05T14:16:39.367 に答える
0

このようなタスクはデコレータで処理できます。

import logging
from functools import wraps

def log_ex(func):
    @wraps(func)
    def _wrapper(*args, **kwargs):
        try:
            func(*args, **kwargs)
        except Exception:
            logging.exception('...')
    return _wrapper

@log_ex
def this_may_cause_an_exception():
    print 'this_may_cause_an_exception'
    raise RuntimeError()

@log_ex
def but_i_wanna_run_this():
    print 'but_i_wanna_run_this'

def test():
    this_may_cause_an_exception()
    but_i_wanna_run_this()

テスト関数の呼び出しは次のようになります(両方の関数が実行されたことを示します)。

>>> test()
this_may_cause_an_exception
ERROR:root:...
Traceback (most recent call last):
  File "<stdin>", line 5, in _wrapper
  File "<stdin>", line 4, in my_func
RuntimeError
but_i_wanna_run_this
于 2012-06-05T14:34:14.607 に答える
0

提供された回答とは別に、1行のtry-exceptステートメントが提案されていることに注意する価値があると思います-関連するPEP 463を残念な拒否通知とともに参照してください。

""" I want to reject this PEP. I think the proposed syntax is acceptable given the
desired semantics, although it's still a bit jarring. It's probably no worse than the
colon used with lambda (which echoes the colon used in a def just like the colon here
echoes the one in a try/except) and definitely better than the alternatives listed.

But the thing I can't get behind are the motivation and rationale. I don't think that
e.g. dict.get() would be unnecessary once we have except expressions, and I disagree 
with the position that EAFP is better than LBYL, or "generally recommended" by Python. 
(Where do you get that? From the same sources that are so obsessed with DRY they'd rather
introduce a higher-order-function than repeat one line of code? :-)

This is probably the most you can get out of me as far as a pronouncement. Given that
the language summit is coming up I'd be happy to dive deeper in my reasons for rejecting
it there (if there's demand).

I do think that (apart from never explaining those dreadful acronyms :-) this was a 
well-written and well-researched PEP, and I think you've done a great job moderating the 
discussion, collecting objections, reviewing alternatives, and everything else that is 
required to turn a heated debate into a PEP. Well done Chris (and everyone who 
helped), and good luck with your next PEP! """
于 2018-10-09T14:24:39.067 に答える
-2
try:
    this_may_cause_an_exception()
except:
    logging.exception('An error occured')
finally:
    but_I_still_wanna_run_this()
    and_this()
    and_also_this()

例外処理のfinallyブロックを使用できます。ただし、実際にはコードのクリーンアップを目的としています。

編集:すべての関数が例外をスローできるとあなたが言ったのを見ました。その場合、larsmansの答えは、関数呼び出しごとに例外をキャッチするために私が考えることができる最もクリーンなものです。

于 2012-06-05T14:12:36.923 に答える