Home > PC

PC Archive

Pythonで標準エラー出力を潰した後は、例外のログを取りましょう

  • 2019-08-02 (金)
  • PC

Pythonを使っているときに、ログを取るのを怠ってエラーが見つからずに苦労したので、ちゃんとログを取りましょう、という話です。(Pythonに慣れている方には、おそらく常識レベルの話だと思います)

普通に処理をしている場合は、予期しない例外が発生すると標準エラー出力に例外のスタックトレースが出力されます。しかし、標準エラー出力を潰した後はスタックトレースが出力されません。

以下のような場合に問題になります。

  • daemon化する場合
  • スレッドを実行する場合

順に説明します。

daemon化する場合

double forkによるdaemon化については、Pythonでは以下のページの例のように行います。

Double forkによるプロセスのデーモン化と、ファイル変更時の自動サーバーリロードの実装 (Python)

この場合、標準エラー出力が潰されているので、 daemon化した後に例外が発生しても、 例外のスタックトレースはどこにも出力されません。

以下のようにすると、例外のログがloggerで出力できます。

def main():
    logger = getLogger()
    handler = FileHandler("./test.log")
    logger.addHandler(handler)

    daemonize() # double forkした後に標準エラー出力を潰す

    try:
        do_process() #ここで例外が発生したら、下のexceptでキャッチする
    except Exception as e:
        logger.exception("Exception {0} occured".format(e))

    

スレッドを実行する場合

さらに、daemon化してからスレッドを実行する場合、親スレッドのtry-exceptではスレッド内での例外は捕捉されず、例外のスタックトレースはどこにも出力されません。 スレッドのrun()で、例外を捕捉してログを出力する必要があります。

class TestThread(threading.Thread):
    _logger = getLogger(__name__)

    def run(self):
        try:
            self._do_process() #ここで例外が発生したら、下のexceptでキャッチする
        except Exception as e:
            self._logger.exception("Exception {0} occured".format(e))

def main():
    logger = getLogger()
    handler = FileHandler("./test.log")
    logger.addHandler(handler)

    daemonize() # double forkした後に標準エラー出力を潰す

    try:
        thread = TestThread()
        thread.start() # thread.run()で例外が発生しても、このtry-exceptでは捕捉できない
    except Exception as e:
        logger.exception("Exception {0} occured".format(e))

そんなこんなでうじゃうじゃ。

昨晩のmirakurunのエラーログ

  • 2018-04-01 (日)
  • PC

4/1の3:08にmirakurunがエラーで再起動していたのでその時のログをメモ。

まず、mirakurun.stdout.log

<--- Last few GCs --->

[22698:0x27abf40] 120047592 ms: Scavenge 57.6 (269.9) -> 53.7 (269.9) MB, 2.7 / 0.0 ms allocation failure
[22698:0x27abf40] 120048005 ms: Scavenge 57.6 (269.9) -> 53.7 (269.9) MB, 2.1 / 0.0 ms allocation failure
[22698:0x27abf40] 120048221 ms: Scavenge 57.6 (269.9) -> 55.6 (269.9) MB, 3.2 / 0.0 ms allocation failure
[22698:0x27abf40] 120048241 ms: Scavenge 57.6 (269.9) -> 57.6 (277.9) MB, 5.1 / 0.0 ms allocation failure

<--- JS stacktrace --->
Cannot get stack trace in GC

次に、mirakurun.stderr.log

FATAL ERROR: Scavenger: semi-space copy
Allocation failed - process out of memory
1: node::Abort() [Mirakurun: Server]
2: 0x11e73ec [Mirakurun: Server]
3: v8::Utils::ReportOOMFailure(char const*, bool) [Mirakurun: Server]
4: v8::internal::V8::FatalProcessOutOfMemory(char const*, bool) [Mirakurun: Server]
5: 0xad230b [Mirakurun: Server]
6: v8::internal::Scavenger::ScavengeObject(v8::internal::HeapObject**, v8::internal::HeapObject*) [Mirakurun: Server]
7: v8::internal::Scavenger::Process(v8::internal::Scavenger::Barrier*) [Mirakurun: Server]
8: v8::internal::ScavengingTask::RunInParallel() [Mirakurun: Server]
9: v8::internal::ItemParallelJob::Task::RunInternal() [Mirakurun: Server]
10: v8::internal::ItemParallelJob::Run() [Mirakurun: Server]
11: v8::internal::Heap::Scavenge() [Mirakurun: Server]
12: v8::internal::Heap::PerformGarbageCollection(v8::internal::GarbageCollector, v8::GCCallbackFlags) [Mirakurun: Server]
13: v8::internal::Heap::CollectGarbage(v8::internal::AllocationSpace, v8::internal::GarbageCollectionReason, v8::GCCallbackFlags) [Mirakurun: Server]
14: v8::internal::Factory::NewRawTwoByteString(int, v8::internal::PretenureFlag) [Mirakurun: Server]
15: v8::internal::IncrementalStringBuilder::Extend() [Mirakurun: Server]
16: v8::internal::JsonStringifier::Result v8::internal::JsonStringifier::Serialize_(v8::internal::Handle, bool, v8::internal::Handle) [Mirakurun: Server]
17: v8::internal::JsonStringifier::Result v8::internal::JsonStringifier::Serialize_(v8::internal::Handle, bool, v8::internal::Handle) [Mirakurun: Server]
18: v8::internal::JsonStringifier::SerializeArrayLikeSlow(v8::internal::Handle, unsigned int, unsigned int) [Mirakurun: Server]
19: v8::internal::JsonStringifier::Result v8::internal::JsonStringifier::Serialize_(v8::internal::Handle, bool, v8::internal::Handle) [Mirakurun: Server]
20: v8::internal::JsonStringifier::Stringify(v8::internal::Handle, v8::internal::Handle, v8::internal::Handle) [Mirakurun: Server]
21: v8::internal::Builtin_JsonStringify(int, v8::internal::Object**, v8::internal::Isolate*) [Mirakurun: Server]
22: 0x2c33ba40697d

その時のメモリ使用量グラフ

4Kモニタ導入

  • 2017-12-12 (火)
  • PC

iiyamaのProLite B2875UHSUという28インチ4Kモニタを導入しました。

以下とりあえず箇条書き。後で清書するかも。

  • 重量は7.5kg。最近の液晶モニターとしては重いと思いますが、リプレース元のHD2441W(2007年に買ったFull HD)が10.3kgだったので、個人的にはむしろ軽量化。
  • コントラスト拡張をOnにすると、輝度の設定ができなくなるので、とても明るくなって使いづらいです。常用するかどうかは検討中。
  • 「ディスプレイ設定」で「テキスト、アプリ、その他の項目のサイズを変更する」を「150%(推奨)」にして使っています。これより小さいと確かに辛い。
  • ドットピッチが細かくなってフォントレンダリングが綺麗になるので、今まで使っていたMacTrayは無効化しました。
  • 上の状態でExcelの新規ワークシートを開くと、AM(39)列67行まで1画面で表示されます。これは広い! (Full HDのスケーリング100%だとAC(29)列49行まで)
  • Firefoxの表示がすごく小さくなるので、about:configからlayout.css.devPixelsPerPxを1.5に
  • Janetterの表示もすごく小さくなるので、フォントサイズを「大きめ」などにして対処しました。ただこれだと文字がボケます。Creators Update 2で追加された高DPI設定も指定でき、それだと文字はボケないのですが、今度はアイコン等が小さすぎるという問題が発生。高DPI用のテーマを作るか、カスタムCSSで対処するか。

最近買ったもの

  • 2017-07-03 (月)
  • PC

PC・スマホ関係で最近買ったもの。

NuAns NEO [Reloaded]

NuAns NEO [Reloaded] 1NuAns NEO [Reloaded] 2NuAns NEO [Reloaded] 3

「日本メーカー設計で素のAndroidスマホ」という謳い文句に惹かれて購入。性能は十分なのだが、カメラアプリが残念で手ぶれとかピント外れとかしまくる。そこさえ改善されれば良いんだけど。

カバーは購入時に内蔵されている半透明カバーの他に、予約特典でフリップケースがついてきて、更にTwoToneのサフラン(上)とカーキ(下)を買い足した。気分によって変える予定。

Seagate IronWolf 8TB

NASのHDD(6TB×4のRAIDZ)が手狭になってきたので、8TB×4に買い換え。NTT-Xでクーポン使用して29800円だった。WD Redだと35000円ぐらいするので、こちらを選択。

USB Type-C/USB-A充電器 ミヨシ IPA-C01

今までは、USB Type-CはNexus5x付属のACアダプタ、USB-AはAnkerの5Portものを使ってたんだけど、まとめたくなったのでヨドバシで購入。

USB Type-CのACアダプタは、まだ過渡期らしく、規格に適合しないものがいろいろあったりするらしいのだけど、このACアダプタは「機器を接続しないと電圧が印加されない(電圧電流チェッカのみ繋いで確認)」「QCには対応せずUSB PDのみ」なので、規格にはそこそこ適合していそう。

USB Type-C 電流・電圧チェッカ ミヨシ STE-02

STE-02

USB PDに対応した電流・電圧チェッカが欲しかったので、ヨドバシで購入。値段の2000円は高い気もしたけど、PD対応ならこんなものか。

私のMastodonアカウント一覧(常時更新)

  • 2017-04-19 (水)
  • PC

ホーム > PC

Search
Feeds
Meta

Return to page top