78

Python で multiprocessing.Process クラスを使用しているときに、特定のプロセスから stdout 出力をログに記録する方法はありますか?

4

5 に答える 5

64

最も簡単な方法は、単にオーバーライドすることsys.stdoutです。マルチプロセッシングマニュアルの例を少し変更します。

from multiprocessing import Process
import os
import sys

def info(title):
    print title
    print 'module name:', __name__
    print 'parent process:', os.getppid()
    print 'process id:', os.getpid()

def f(name):
    sys.stdout = open(str(os.getpid()) + ".out", "w")
    info('function f')
    print 'hello', name

if __name__ == '__main__':
    p = Process(target=f, args=('bob',))
    p.start()
    q = Process(target=f, args=('fred',))
    q.start()
    p.join()
    q.join()

そしてそれを実行します:

$ ls
m.py
$ python m.py
$ ls
27493.out 27494.out m.py
$ cat 27493.out
関数f
モジュール名:__ main__
親プロセス:27492
プロセスID:27493
こんにちはボブ
$ cat 27494.out
関数f
モジュール名:__ main__
親プロセス:27492
プロセスID:27494
こんにちはフレッド

于 2009-10-01T03:30:09.967 に答える
21

@Mark Rushakoffの回答に追加することは2つだけです。デバッグ時に、呼び出しのbufferingパラメーターを 0に変更すると非常に便利であることがわかりました。open()

sys.stdout = open(str(os.getpid()) + ".out", "a", buffering=0)

そうしないと、出力ファイルを ing するときに結果が非常に断続的になる可能性があるため、気が狂います素晴らしいです。tail -fbuffering=0tail -f

そして、完全を期すために、自分自身を支持してリダイレクトsys.stderrしてください。

sys.stderr = open(str(os.getpid()) + "_error.out", "a", buffering=0)

また、便宜上、必要に応じて別のプロセス クラスにダンプすることもできます。

class MyProc(Process):
    def run(self):
        # Define the logging in run(), MyProc's entry function when it is .start()-ed 
        #     p = MyProc()
        #     p.start()
        self.initialize_logging()

        print 'Now output is captured.'

        # Now do stuff...

    def initialize_logging(self):
        sys.stdout = open(str(os.getpid()) + ".out", "a", buffering=0)
        sys.stderr = open(str(os.getpid()) + "_error.out", "a", buffering=0)

        print 'stdout initialized'

対応する要点はこちら

于 2014-05-29T15:51:01.913 に答える
12

メソッド(すぐに、またはが検出されるまで累積する)が呼び出すクラス(またはログに記録するその他の方法)がsys.stdout = Logger()どこにあるかを設定できます。動作中のこの例。Loggerwrite\nlogging.info

「与えられた」プロセスの意味はわかりませんが(誰が与えたのか、他のすべてのプロセスと何が違うのか...?)、もしあなたがその時にどのプロセスを選び出したいのかを知っているのならインスタンス化すると、そのtarget関数(およびそれのみ)(またはサブクラスrunでオーバーライドするメソッド)Processを、このsys.stdout「リダイレクト」を実行するラッパーにラップし、他のプロセスをそのままにしておくことができます。

多分あなたがスペックを少し釘付けにすれば私はもっと詳細に助けることができます...?

于 2009-10-01T03:29:57.173 に答える
1

log_to_stderr() 関数は最も簡単なソリューションです。

PYMOTWから:

multiprocessing には、log_to_stderr() と呼ばれるロギングを有効にする便利なモジュール レベル関数があります。ロギングを使用してロガー オブジェクトを設定し、ハンドラーを追加して、ログ メッセージが標準エラー チャネルに送信されるようにします。デフォルトでは、ログ レベルは NOTSET に設定されているため、メッセージは生成されません。別のレベルを渡して、必要な詳細レベルにロガーを初期化します。

import logging
from multiprocessing import Process, log_to_stderr

print("Running main script...")

def my_process(my_var):
    print(f"Running my_process with {my_var}...")

# Initialize logging for multiprocessing.
log_to_stderr(logging.DEBUG)

# Start the process.
my_var = 100;
process = Process(target=my_process, args=(my_var,))
process.start()
process.kill()

このコードは両方の print() ステートメントを stderr に出力します。

于 2021-02-10T06:51:28.097 に答える