在python中使用multiprocessing.Process类时,有没有办法记录给定进程的stdout输出?
答案 0 :(得分:50)
最简单的方法可能是覆盖sys.stdout
。稍微修改the multiprocessing manual的示例:
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 function f module name: __main__ parent process: 27492 process id: 27493 hello bob $ cat 27494.out function f module name: __main__ parent process: 27492 process id: 27494 hello fred
答案 1 :(得分:14)
我只会向@Mark Rushakoff回答两件事。在调试时,我发现将buffering
调用的open()
参数更改为0非常有用。
sys.stdout = open(str(os.getpid()) + ".out", "a", buffering=0)
否则,疯狂,因为当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'
答案 2 :(得分:11)
您可以设置sys.stdout = Logger()
其中Logger
是一个类write
方法(立即或累积,直到检测到\n
)调用logging.info
(或你想要记录的任何其他方式)。 An example of this in action.
我不确定你所说的“给定”过程是什么意思(谁给了它,它与其他所有人区别开来......?),但如果你的意思是你知道你想要用什么过程来表达在实例化它的时候,那么你可以将它的target
函数(仅限于) - 或者你在run
子类中覆盖的Process
方法 - 包装到一个包装器中执行此sys.stdout“重定向” - 并保留其他进程。
也许如果你确定了一些规格,我可以更详细地帮助......?
答案 3 :(得分:3)
这是捕获multiprocessing.Process和io.TextIOWrapper的标准输出的简单明了的方法:
import app
import io
import sys
from multiprocessing import Process
def run_app(some_param):
out_file = open(sys.stdout.fileno(), 'wb', 0)
sys.stdout = io.TextIOWrapper(out_file, write_through=True)
app.run()
app_process = Process(target=run_app, args=('some_param',))
app_process.start()
# Use app_process.termninate() for python <= 3.7.
app_process.kill()
答案 4 :(得分:1)
log_to_stderr() 函数是最简单的解决方案。
来自PYMOTW:
<块引用>multiprocessing 有一个方便的模块级函数来启用名为 log_to_stderr() 的日志记录。它使用日志记录设置一个记录器对象并添加一个处理程序,以便将日志消息发送到标准错误通道。默认情况下,日志级别设置为 NOTSET,因此不会生成任何消息。传递不同的级别以将记录器初始化为所需的详细级别。
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。