Pythonロギング-インポートされたモジュールからのロギングを無効にします


100

Pythonロギングモジュールを使用していますが、インポートしたサードパーティモジュールによって出力されたログメッセージを無効にしたいと思います。たとえば、私は次のようなものを使用しています。

logger = logging.getLogger()
logger.setLevel(level=logging.DEBUG)
fh = logging.StreamHandler()
fh_formatter = logging.Formatter('%(asctime)s %(levelname)s %(lineno)d:%(filename)s(%(process)d) - %(message)s')
fh.setFormatter(fh_formatter)
logger.addHandler(fh)

これにより、logger.debug( "my message!")を実行するとデバッグメッセージが出力されますが、インポートしたモジュールからのデバッグメッセージ(要求など)も出力されます。

興味のあるモジュールからのログメッセージのみを表示したいのですが、ロギングモジュールにこれを実行させることはできますか?

理想的には、「ModuleX、ModuleY」からのメッセージを印刷し、他のすべてを無視するようにロガーに指示できるようにしたいと思います。

私は以下を見ましたが、インポートされた関数を呼び出す前にロギングを無効/有効にする必要はありません: logging-インポートされたモジュールログを無視する方法は?

回答:


70

問題は、getLogger引数なしで呼び出すとルートロガーが返されるため、レベルをlogging.DEBUG設定すると、そのロガーを使用する他のモジュールのレベルも設定されることです。

これは、ルートロガーを使用しないことで解決できます。これを行うには、引数として名前を渡すだけです。たとえば、モジュールの名前です。

logger = logging.getLogger('my_module_name')
# as before

これにより、新しいロガーが作成されるため、他のモジュールのログレベルが誤って変更されることはありません。


後者はルートロガーのメソッドを呼び出す便利な関数logger.debugであるlogging.debugため、明らかに代わりに使用する必要がありますdebug

これは、高度なロギングチュートリアルで説明されています。また、どのモジュールがログメッセージをトリガーしたかを簡単な方法で知ることができます。


37
__name__rを使用してロガーを作成していますが、インポートされたモジュールのログが表示されます。ini構成ファイルを使用してログを構成しようとしていますが、どうすればよいですか?
Durga Swaroop 2018年

8
でロガーを作成すること__name__も私にはうまくいきませんでした。「モジュール」ではなくスタンドアロンスクリプトを使用しているためかもしれません。私にとってうまくいったのはmatpplotlib、を介してインポートされたモジュール(私の場合は)のログを構成logging.getLogger("matplotlib").setLevel(logging.WARNING)し、を介してスクリプトのログを構成することでしたlogging.basicConfig
BLI

1
「明らかlogger.debugに、代わりに使用する必要がある」という行の値を強調したかっただけですlogging.debugロガーの代わりにロギングを使用するのは簡単な間違いですが、セットアップしたい巧妙な構成がすべて失われます。私はここ数時間これを生きてきました!
timdadev

@bliライブラリを開発するときと実行可能ファイルを開発するときのロギングには大きな違いがあります。基本的に:インポートすることを目的としたモジュール/パッケージを作成している場合は、何も構成しないでください。モジュールには、logger = logging.getLogger('package.my_module')および可能性のある呼び出しのみが含まれている必要があり、logger.debug/warningロギングレベルまたはハンドラーの構成は含まれていません。そこでバイナリアプリケーションを作成するときは、さまざまなログとハンドラーのレベルを決定する必要があります。ロギング構成を含むライブラリは常に問題になります。
バクリウ

私の場合、インポートするパッケージはルートロガーを使用します(経由logging.info)。このパッケージからrootログを明確に無効にする方法はありますか?
ianS

45

Pythonloggingパッケージを使用する場合は、それを使用するすべてのモジュールでロガーを定義するのが一般的な規則です。

logger = logging.getLogger(__name__)

を含む多くの人気のあるPythonパッケージがこれを行いrequestsます。パッケージがこの規則を使用している場合、ロガー名はパッケージと同じ名前になる(またはそのロガーの子になる)ため、ログのログを簡単に有効/無効にできます。他のロガーと同じファイルに記録することもできます。

logger = logging.getLogger(__name__)
logger.setLevel(logging.DEBUG)

requests_logger = logging.getLogger('requests')
requests_logger.setLevel(logging.DEBUG)

handler = logging.StreamHandler()
handler.setLevel(logging.DEBUG)
logger.addHandler(handler)
requests_logger.addHandler(handler)

15
公式の基本チュートリアルのようにロガーを構成しようとすると、logging.basicConfig(...)すべてのロガーがlogging.lastResort、ハンドラーが指定されていない場合は(Python 3.2以降、stderr)に出力されるか、設定したハンドラーに出力されることに注意してください。したがって、使用しないでください。使用しないと、とにかくすべてのログメッセージが引き続き表示されます。
user136036 2018

43

これが投稿に適しているかどうかはわかりませんが、私は長い間立ち往生していて、他のどこにも見つからなかったので、同じ問題を抱えている人を助けたいと思っていました!

ロギングの高度なチュートリアルトラブルシューティングの非常に簡単なドキュメントに従っているにもかかわらず、matplotlibからデバッグログを取得していました。main()あるファイルでロガーを開始し、別のファイル(matplotlibをインポートした場所)からプロットを作成する関数をインポートしていました。

私にとってうまくいったのは、メインファイルの他のモジュールのようにインポートした後ではなく、インポートするにmatplotlibのレベルを設定することでした。これは私には直感に反しているように思えたので、まだインポートされていないロガーの構成を設定する方法について誰かが洞察を持っているなら、これがどのように機能するかを知りたいと思います。ありがとう!

私のメインファイル:

import logging
import requests
logger = logging.getLogger(__name__)
logger.setLevel(logging.DEBUG)
logging.getLogger('requests').setLevel(logging.DEBUG)

def main():
  ...

私のplot.pyファイル:

import logging
logging.getLogger('matplotlib').setLevel(logging.WARNING)
import matplotlib.pyplot as plt

def generatePlot():
  ...

エラーが発生しました:「Logger」オブジェクトに属性「DEBUG」がありません。 logger.DEBUGあるべきlogging.DEBUG
foxiris

ありがとう!それは本当に役立ちます!メインのログ設定の後、matplotlibをインポートするコマンドの前にmatplotlibのログレベルを設定しました。解決しました!
GPH

モジュールをインポートmatplotlibしたWARNING にログをに設定しました。インポートする前にモジュールを追加すると、lintエラーが発生するためです。それはまだ私のために働いた。matplotlib==3.3.2役立つ場合は、Python3.7で使用しています。
終了-2-終了

9

@Bakuriuは非常にエレガントに機能を説明しています。逆に、このgetLogger()メソッドを使用して、不要なロガーを取得して再構成/無効化することができます。

また、以前に定義された(つまり、インポートされたモジュール内の)ロガーを無効にするlogging.fileConfig()というパラメーターを受け入れるメソッドを追加したいと思いましたdisable_existing_loggers


9

これにより、インポートされたモジュールによって作成されたものなど、既存のすべてのロガーが無効になりますが、ルートロガーは引き続き使用されます(外部ファイルをロードする必要はありません)。

logging.config.dictConfig({
    'version': 1,
    'disable_existing_loggers': True,
})

最初にログに記録したくないすべてのモジュールをインポートする必要があることに注意してください!そうしないと、それらは「既存のロガー」とは見なされません。次に、それらのモジュールのすべてのロガーを無効にします。これにより、重要なエラーも見逃してしまう可能性があります。

コンフィギュレーションのための関連オプションを使用して、より詳細な例については、https://gist.github.com/st4lk/6287746を、そしてここでは、との設定のためのYAMLを使用して(部分的に取り組んで)一例であるcoloredlogライブラリ。


あなたの質問は何ですか?
user1767754 2017

1
これrequestはたとえば機能しますが、インポートしたモジュールが、後で呼び出すクラス内にロガーを作成するAPScheduler場合は機能しませんBackgroundScheduler.BackgroundScheduler()。たとえば、を呼び出す場合は機能しません。解決策については、こちらをご覧ください:stackoverflow.com/a/48891485/2441026
user136036 2018

これは、YAML設定ファイルで私の場合のために働く
user4015990

4

次のようなものを使用できます。

logging.getLogger("imported_module").setLevel(logging.WARNING)
logging.getLogger("my_own_logger_name").setLevel(logging.DEBUG)

これにより、インポートされたモジュールが同じレベルを使用するのを防ぎながら、自分のモジュールのログレベルをDEBUGに設定します。

注: "imported_module"に置き換えることができますimported_module.__name__(引用符なし)、および"my_own_logger_name"に置き換えることができる__name__ことは、あなたがそれを行うことを好む方法だ場合。


1

私も同じ問題を抱えていました。他のすべてのpyファイルにインポートするlogging_config.pyファイルがあります。logging_config.pyファイルで、ルートロガーのログレベルをERROR(デフォルトでは警告)に設定しました。

logging.basicConfig(
    handlers=[
        RotatingFileHandler('logs.log',maxBytes=1000, backupCount=2),
        logging.StreamHandler(), #print to console
    ],
    level=logging.ERROR
)

他のモジュールでは、logging_config.pyをインポートし、新しいロガーを宣言して、そのレベルをデバッグに設定します。

log = logging.getLogger(__name__)
log.setLevel(logging.DEBUG)

このようにして、pyファイルにログインしたものはすべてログに記録されますが、urllib、request、boto3などのインポートされたモジュールによってデバッグおよび情報レベルでログに記録されたものはログに記録されません。ルートロガーのレベルをERRORに設定したため、これらのインポートモジュールにエラーがある場合は、ログに記録されます。


0

考慮すべきもう1つのことは、Loggerクラスのpropagateプロパティです。

たとえば、SOAP呼び出しを処理するためのpy-sudsライブラリは、ERRORに設定されていても

logging.getLogger('suds.client').setLevel(logging.ERROR)
logging.getLogger('suds.transport').setLevel(logging.ERROR)
logging.getLogger('suds.xsdschema').setLevel(logging.ERROR)
logging.getLogger('suds.wsdl').setLevel(logging.ERROR)

sxbasics.pycreationgと呼ばれるモジュールに関するログログ大量のログ

ここに画像の説明を入力してください

ログの伝播はデフォルトでTrueであるため、Falseに設定すると、代わりに514MBのログが回復されました。

import logging
logging.getLogger("suds").propagate = False
logging.getLogger('suds.client').setLevel(logging.ERROR)
logging.getLogger('suds.transport').setLevel(logging.ERROR)
logging.getLogger('suds.xsdschema').setLevel(logging.ERROR)
logging.getLogger('suds.wsdl').setLevel(logging.ERROR)
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.