Pythonでトレースバックログが出力されなくなった原因を知りたいです。


## 質問の概要

今までPythonでトレースバックログは以下で出していました。

[code]

    import traceback
    print(traceback.fornat_exc())
    
[/code]

2023/10/4に動作検証した時もスタックダンプのログが出ることを確認できていました。  
しかし、本日(2023/10/8)試したら`NoneType: None`しかでなくなっていました。  
別の実装で回避はできるのですが、万が一の保険として入れてる処理が何もしてないのに想定外の動きをするとか恐怖でしかありません。  
私の開発環境固有の問題なのか、他に原因があるのか？原因を知りたくて質問しました。

## 試した環境(実行環境/pythonバージョンのフォーマットで記載)

※Windows PCを2台所有しており、win環境と仮想環境の4パターンで試しています。

  * Windows 11 pro 22H2 / Python 3.11.6
  * WSL(Ubuntu 22.04.2 LTS) / python 3.10.12
  * Windows 10 pro 22H2 / Python 3.11.6
  * VirtualBox(Ubuntu 22.04.2 LTS) / 3.10.12

## 検証用のソース

[code]

    import traceback
    import logging
    
    
    def hoge():
        print("---------------1)traceback.format_exc()")
        logging.error(traceback.format_exc())
        print("---------------2)traceback.extract_stack()")
        logging.error(traceback.extract_stack())
        print("---------------3)logging.error(stack_info=True)")
        logging.error("(=^・^=)", stack_info=True)
    
    def main():
        hoge()
    
    main()
    
[/code]

## 実行結果

※動作確認した環境すべてで`1)traceback.format_exc()`はスタックダンプログが出力されませんでした。

[code]

    ---------------1)traceback.format_exc()
    ERROR:root:NoneType: None
    
    ---------------2)traceback.extract_stack()
    ERROR:root:[<FrameSummary file /home/hirao/_git/sample_python/aaaa.py, line 17 in <module>>, <FrameSummary file /home/hirao/_git/sample_python/aaaa.py, line 15 in main>, <FrameSummary file /home/hirao/_git/sample_python/aaaa.py, line 9 in hoge>]
    ---------------3)logging.error(stack_info=True)
    ERROR:root:(=^・^=)
    Stack (most recent call last):
      File "/home/hirao/_git/sample_python/aaaa.py", line 37, in <module>
        main()
      File "/home/hirao/_git/sample_python/aaaa.py", line 35, in main
        hoge()
      File "/home/hirao/_git/sample_python/aaaa.py", line 31, in hoge
        logging.error("(=^・^=)", stack_info=True)```
    
[/code]




Pythonの3.10までと3.11以後では細部に違いがあるようですが、いずれも例外が発生していない状況では元となる情報を保持している`sys`モジュールの関数からは`None`が返ることになっています。

なので質問に書かれている`ERROR:root:NoneType: None`が表示されるのは通常の状態だということでしょう。

`以前にスタックダンプのログが出ていた`ならば、その時点で例外が発生した記録が`sys`モジュールに残っていたということでしょう。

以下に根拠となる資料を提示しておきます。

* * *

バージョン 3.11 での説明。

[traceback ---
スタックトレースの表示または取得](https://docs.python.org/ja/3.11/library/traceback.html)

> [traceback.format_exc(limit=None,
> chain=True)](https://docs.python.org/ja/3.11/library/traceback.html#traceback.format_exc)  
>  これは、`print_exc(limit)` に似ていますが、ファイルに出力する代わりに文字列を返します。

> [traceback.print_exc(limit=None, file=None,
> chain=True)](https://docs.python.org/ja/3.11/library/traceback.html#traceback.print_exc)  
>  `print_exception(sys.exception(), limit, file, chain)` の省略表現です。

[sys --- システムパラメータと関数](https://docs.python.org/ja/3.11/library/sys.html)

>
> [sys.exception()](https://docs.python.org/ja/3.11/library/sys.html#sys.exception)  
>  This function, when called while an exception handler is executing (such as
> an `except` or `except*` clause), returns the exception instance that was
> caught by this handler. When exception handlers are nested within one
> another, only the exception handled by the innermost handler is accessible.  
>  この関数は、例外ハンドラーの実行中に呼び出されると (Except 句やException*
> 句など)、このハンドラーによってキャッチされた例外インスタンスを返します。
> 例外ハンドラーが相互にネストされている場合、最も内側のハンドラーによって処理される例外のみにアクセスできます。

> If no exception handler is executing, this function returns None.  
>  例外ハンドラーが実行されていない場合、この関数は `None` を返します。

> バージョン 3.11 で追加.

* * *

バージョン 3.10
での説明はこちらで`sys.exception()`はまだ作られていないため`sys.exc_info()`が使われていますが、こちらも例外が発生していない場合は`None`が返っています。

traceback.format_exc()の説明は変わらず`print_exc(limit)`と類似ということです。

> [traceback.print_exc(limit=None, file=None,
> chain=True)](https://docs.python.org/ja/3.10/library/traceback.html#traceback.print_exc)  
>  `print_exception(*sys.exc_info(), limit, file, chain)` の省略表現です。

>
> [sys.exc_info()](https://docs.python.org/ja/3.10/library/sys.html#sys.exc_info)  
>  現在処理中の例外を示す 3
> 個の値のタプルを返します。この値は、現在のスレッドおよび現在のスタックフレームのものです。現在のスタックフレームが例外処理中でない場合、例外処理中のスタックフレームが見つかるまでその呼び出したスタックフレームや呼び出し元などを調べます。ここで、"例外処理中"
> とは "except 節を実行中である" フレームを指します。どのスタックフレームでも、最後に処理した例外の情報のみを参照できます。

> If no exception is being handled anywhere on the stack, a tuple containing
> three `None` values is returned. Otherwise, the values returned are `(type,
> value, traceback)`.  
>  スタック上のどこにも例外が処理されていない場合は、3 つの None 値を含むタプルが返されます。 それ以外の場合、返される値は
> (type、value、traceback) です。

