Python で multiprocessing.Process クラスを使用しているときに、特定のプロセスから stdout 出力をログに記録する方法はありますか?
5 に答える
最も簡単な方法は、単にオーバーライドすること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 こんにちはフレッド
@Mark Rushakoffの回答に追加することは2つだけです。デバッグ時に、呼び出しのbuffering
パラメーターを 0に変更すると非常に便利であることがわかりました。open()
sys.stdout = open(str(os.getpid()) + ".out", "a", buffering=0)
そうしないと、出力ファイルを ing するときに結果が非常に断続的になる可能性があるため、気が狂います。素晴らしいです。tail -f
buffering=0
tail -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'
メソッド(すぐに、またはが検出されるまで累積する)が呼び出すクラス(またはログに記録するその他の方法)がsys.stdout = Logger()
どこにあるかを設定できます。動作中のこの例。Logger
write
\n
logging.info
「与えられた」プロセスの意味はわかりませんが(誰が与えたのか、他のすべてのプロセスと何が違うのか...?)、もしあなたがその時にどのプロセスを選び出したいのかを知っているのならインスタンス化すると、そのtarget
関数(およびそれのみ)(またはサブクラスrun
でオーバーライドするメソッド)Process
を、このsys.stdout「リダイレクト」を実行するラッパーにラップし、他のプロセスをそのままにしておくことができます。
多分あなたがスペックを少し釘付けにすれば私はもっと詳細に助けることができます...?
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 に出力します。