在多处理应用程序中,主进程产生多个子进程。每个进程都应运行自己的Tornado ioloop。但是,我注意到,当进程启动时,IOLoop.current()
的所有实例(在主进程和所有子进程中)都是相同的。这是否意味着ioloop.spawn_callback(my_func)
全部在一个ioloop上下文中运行(在主进程中)?
这是我可以提取的一个最小示例:
from tornado.ioloop import IOLoop
import time
from multiprocessing import Process
def sub(i):
print('sub %d: %s' % (i, hex(id(IOLoop.current(True)))))
for i in range(10):
time.sleep(1)
def main():
print('main ', hex(id(IOLoop.current(True))))
for i in range(2):
sub_process = Process(target=sub, args=(i, ))
sub_process.daemon = True
sub_process.start()
time.sleep(5)
main()
输出:
main 0x7f14a09cf750
sub 0: 0x7f14a09cf750
sub 1: 0x7f14a09cf750
是否正确创建了进程,并且不是预期会有多个ioloop实例的行为?
答案 0 :(得分:1)
龙卷风的docs
中提到了这一点重要的是,在派生之前,任何东西都不能碰到全局IOLoop实例(甚至是间接地)
您可以使用经过稍微修改的main
函数来获得所需的行为:
def main():
processes = []
for i in range(2):
process = Process(target=sub, args=(i,))
process.daemon = True
process.start()
processes.append(process)
print('main ', hex(id(IOLoop.current(True))))
time.sleep(5)
输出:
main 0x7fbd4ca0da30
sub 0: 0x7fbd4ca0db50
sub 1: 0x7fbd4ca0dc40
至于解释:共享是由于fork
在Linux中的实现方式所致:使用COW
(写时复制);这意味着除非您在子进程中写入共享对象,否则父级和子级将共享同一对象。子级修改共享对象后,将对其进行复制和更改(这些更改在父级中不可见)。