2017-09-27 19 views
0

logger.exceptionプールで実行するとstacktraceが表示されず、エラーmsgがargとして渡されます。Python - 新しいスレッドでスタックトレースを取得する方法

セットアップ:

import logging 
from concurrent.futures import ThreadPoolExecutor 
logger = logging.getLogger('custom') 
ch = logging.StreamHandler() 
logger.addHandler(ch) 
logger.setLevel(logging.INFO) 
executor = ThreadPoolExecutor(3) 

は、スタックトレースを表示しません:

try: 
    1/0 
except Exception as e: 
    executor.submit(logger.exception, e) 

は、スタックトレースを表示します

try: 
    1/0 
except Exception as e: 
    executor.submit(logger.exception(e)) 
+2

新しいスレッドは新しいスタックを意味します。 –

+0

'logger.exception(e)'のように提出すれば動作します – garg10may

+0

これは 'submit'を呼び出す前にロギングを行うためです。 AFAIRは 'None'でなければならないロギング呼び出しの結果で実際に呼び出されます。 –

答えて

2

問題は、スレッドプールに提出される前にログに記録されているので、このコードは動作します:あなたがスレッドプールに送信しているもの

try: 
    1/0 
except Exception as e: 
    executor.submit(logger.exception(e)) 

現実には、Noneあります。

それが外に例外処理コンテキスト(それは別のスレッドで実行していますとき、それはなります)のだときは動作しませんlogger.exception呼び出しで起こっ魔法のビットがありますので、これは動作しません。

try: 
    1/0 
except Exception as e: 
    executor.submit(logger.exception, e) 

通常、ドキュメントの確認に役立ちます。 .exception() methodについては、

このロガーでレベルERRORのメッセージを記録します。引数はdebug()と解釈されます。例外情報がロギングメッセージに追加されます。このメソッドは、例外ハンドラからのみ呼び出される必要があります。

.debug()のドキュメントの関連部分は次のとおりです。

logging.debug(MSG、* argsを、** kwargsから)

はルートロガーのレベルDEBUGのメッセージをログに記録します。 msgはメッセージフォーマット文字列で、argsは文字列フォーマット演算子を使ってmsgにマージされる引数です。

検査されるkwargsには、3つのキーワード引数があります:exc_infoこれは、falseと評価されない場合は、以下の3つの原因が考えられます。ロギングメッセージに追加される例外情報例外タプル(sys.exc_info()によって返された形式)が提供されている場合は、それが使用されます。それ以外の場合は、例外情報を取得するためにsys.exc_info()が呼び出されます。

ので、この行:

executor.submit(logger.exception, e) 

も例外情報を持っていないログを扱うスレッドで呼び出される原因sys.exc_info()を呼び出します - ので、何のトレースバックが記録されません。代わりに、あなたがしたい:

executor.submit(logger.exception, "error occurred", exc_info=sys.exc_info()) 

だから、最終的な形だで、それは次のようになります。さらに良い

try: 
    1/0 
except Exception as e: 
    executor.submit(logger.exception, "error occurred", exc_info=sys.exc_info()) 

logger.exception()コールを回避し、だけではなく、logger.error()を使用することです:

try: 
    1/0 
except Exception as e: 
    executor.submit(logger.error, "error occurred", exc_info=sys.exc_info()) 

例外メッセージをログのメッセージとして表示するには、元のコードと同じように次のようにします。

try: 
    1/0 
except Exception as e: 
    executor.submit(logger.error, e, exc_info=sys.exc_info()) 

eは、文字列に変換され、トレースバックを記録するメッセージとして使用されます。

+0

'logger.exception'は' exc_info = True'を使った 'logger.error'なので、' logger.error、e、exc_info = sys.exc_info() 'を呼び出すべきです – garg10may

+0

あなたは安全ですlogger.exception 'exc_info'パラメータで例外情報を提供している限り、ここでは' logger.error'が良い選択だと思います。 – jszakmeister

関連する問題