Pythonはどうやって関数ライブラリにログ機能を追加しますか?


問題
ある関数ライブラリにログ機能を追加したいですが、ログ機能を使わないプログラムに影響を与えません。
ソリューション
ログ操作を実行したい関数ライブラリに対しては、独自のロゴオブジェクトを作成し、以下のように初期化します。

# somelib.py

import logging
log = logging.getLogger(__name__)
log.addHandler(logging.NullHandler())

# Example function (for testing)
def func():
  log.critical('A Critical Error!')
  log.debug('A debug message')
この設定を使うと、デフォルトではログは印刷されません。たとえば:

>>> import somelib
>>> somelib.func()
>>>
しかし、ログシステムが設定されている場合、ログメッセージの印刷は有効になります。例えば、

>>> import logging
>>> logging.basicConfig()
>>> somelib.func()
CRITICAL:somelib:A Critical Error!
>>>
討論する
通常は、関数ライブラリコードにログシステムを設定したり、既に存在しているログの設定を仮定したりしてはいけません。
呼び出しgetLogger(__name__) は、呼び出しモジュールと同名のloggerモジュールを作成します。モジュールが唯一ですので、作成したロゴも唯一です。log.addHandler(logging.NullHandler())操作で空きプロセッサを作成したばかりのロゴオブジェクトに結びつけます。すべてのログメッセージの呼び出しはデフォルトでは無視されます。したがって、関数ライブラリを使用するときにログが設定されていないと、メッセージや警告が表示されません。
もう一つのポイントは、各関数ライブラリに対するログの配置は互いに独立していてもよく、他のライブラリのログの配置に影響しないということです。例えば、以下のコードの場合:

>>> import logging
>>> logging.basicConfig(level=logging.ERROR)

>>> import somelib
>>> somelib.func()
CRITICAL:somelib:A Critical Error!

>>> # Change the logging level for 'somelib' only
>>> logging.getLogger('somelib').level=logging.DEBUG
>>> somelib.func()
CRITICAL:somelib:A Critical Error!
DEBUG:somelib:A debug message
>>>
ここで、ルートログはERRORまたはより高いレベルのメッセージのみを出力するように構成される。しかし、somelibのログレベルは、グローバル構成よりも優先度が高い、debugレベルのメッセージを出力できるように個別に構成されている。このように個々のモジュールのログ設定を変更するのはデバッグにとって便利です。すべてのグローバルログの設定を変更する必要がないからです。もっと多く出力したいモジュールのログレベルを変更するだけです。
ロギングHOWTROは、ログモジュールの設定やその他の有用なスキルを詳細に紹介しています。以下を参照してください。
以上はPythonがどうやって関数ライブラリにログ機能を追加しますか?