Tornado ioloop 实例似乎跨进程共享
Tornado ioloop instance seems to be shared across processes
在多处理应用程序中,一个主进程产生多个子进程。每个进程都意味着 运行 它自己的 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 实例?
Tornado 的 docs
中提到了这一点
it is important that nothing touches the global IOLoop instance (even indirectly) before the fork
您可以使用稍微修改的 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中的实现方式:using COW
(copy-on-write);这意味着除非你在 child 进程中 将 写入共享 object,否则 parent 和 child 将共享相同的 object。一旦 child 修改了共享的 object 它将被 copied 和 changed (这些更改不会在 parent) 中可见。
在多处理应用程序中,一个主进程产生多个子进程。每个进程都意味着 运行 它自己的 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 实例?
Tornado 的 docs
中提到了这一点it is important that nothing touches the global IOLoop instance (even indirectly) before the fork
您可以使用稍微修改的 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中的实现方式:using COW
(copy-on-write);这意味着除非你在 child 进程中 将 写入共享 object,否则 parent 和 child 将共享相同的 object。一旦 child 修改了共享的 object 它将被 copied 和 changed (这些更改不会在 parent) 中可见。