63095


python の例外出力がみにくいので  
例外が起こった場所だけをピンポイントで表示できるようにしたいです

[pythonですべての例外をキャッチし、詳細を表示させたい。](https://ja.stackoverflow.com/questions/6972/python%E3%81%A7%E3%81%99%E3%81%B9%E3%81%A6%E3%81%AE%E4%BE%8B%E5%A4%96%E3%82%92%E3%82%AD%E3%83%A3%E3%83%83%E3%83%81%E3%81%97-%E8%A9%B3%E7%B4%B0%E3%82%92%E8%A1%A8%E7%A4%BA%E3%81%95%E3%81%9B%E3%81%9F%E3%81%84/7008)

こちらによると例外位置を表示させるには

  * sys.exc_info()
  * traceback.print_exc()

の２つがあるみたいで

たとえばこんな感じのサブルーチンのライブラリ内でエラーが出るコードをかいたときに

[code]

    import sys
    import json
    
    def sub():
      return json.load('{') # わざと例外
    
    def main():
      try:
        sub()
      except:
        # sys.exec_info をつかう場合
        exc_type, exc_obj, exc_tb = sys.exc_info()
        print("[%s] %s\nat file %s, line %s\n---\n" % (exc_type.__name__,
                                                   exc_obj,
                                                   exc_tb.tb_frame.f_code.co_filename.split('/')[-1], 
                                                   exc_tb.tb_lineno,
                                                   ))
    
        # print_exec を使う場合
        import traceback
        traceback.print_exc()
    
    main()
    
[/code]

### sys.exc_info()

[code]

    [AttributeError] 'str' object has no attribute 'read'
    at file test.py, line 9
    
[/code]

sub の中でおこった例外も main の位置しか表示してくれません

### traceback.print_exc()

[code]

    Traceback (most recent call last):
      File "test.py", line 9, in main
        sub()
      File "test.py", line 5, in sub
        return json.load('{')
      File "/user/local/.pyenv/versions/3.7.5/lib/python3.7/json/__init__.py", line 293, in load
        return loads(fp.read(),
    AttributeError: 'str' object has no attribute 'read'
    
[/code]

ライブラリの中まで表示して見にくいですし、  
ターミナル出力にはかれてしまうので文字列で取得する方法がわかりません

### 出力したい内容

ライブラリの中は無視したユーザファイルの中の一番深い位置

[code]

    [AttributeError] 'str' object has no attribute 'read'
      File "test.py", line 5, in sub
        return json.load('{')
    
[/code]

とだけ表示できるようにファイルのプレフィックスとかでフィルタしたいです

`traceback.print_exc()`の内容を文字列で取得できれば  
１行ずつ分解して /usr/local が含まれる行とそのつぎの行は削除  
みたいなことができるかと思うのですが

きれいな方法はありませんか？


CC BY-SA 4.0
2020-02-16T12:13:27.100
63093
2020-02-16T13:49:55.523
2020-02-16T12:48:39.093
32986
question
python
例外を見やすく表示したい


スタックトレースはFrameSummary毎に分かれてますので、文字列で処理しようとせずエラーから必要なスタックだけ抜き出して表示すればいいんじゃないかと思います。

[code]

    #!/usr/bin/env python3
    import json
    from traceback import TracebackException
    from traceback import StackSummary
    
    
    def sub():
        return json.load('{')  # わざと例外
    
    
    def main():
        try:
            sub()
        except Exception as err:
            tb = TracebackException.from_exception(err)
    
            caller = None
            for stack in tb.stack:
                if not stack.filename.startswith("/usr/local"):
                    caller = stack
    
            summary = StackSummary.from_list([caller])
    
            print(err)
            print(''.join(summary.format()))
    
    
    main()
    
[/code]

手元ではこんな感じになりました:

[code]

    'str' object has no attribute 'read'
      File "test.py", line 8, in sub
        return json.load('{')  # わざと例外
    
[/code]


CC BY-SA 4.0
2020-02-16T13:49:55.523
63095
2020-02-16T13:49:55.523
62
63093
answer