Tornado ioloop实例似乎在进程之间共享

时间:2020-04-20 02:59:03

标签: python tornado ioloop

在多处理应用程序中,主进程产生多个子进程。每个进程都应运行自己的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实例的行为?

1 个答案:

答案 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(写时复制);这意味着除非您在子进程中写入共享对象,否则父级和子级将共享同一对象。子级修改共享对象后,将对其进行复制更改(这些更改在父级中不可见)。