是对进程池中的contextvars所做的更改未传播到运行asyncio循环的主进程

时间:2019-05-25 05:30:00

标签: python python-multiprocessing python-asyncio python-3.7

下面是我运行的代码段:

from concurrent.futures import ProcessPoolExecutor

import asyncio
import contextvars


ctx = contextvars.ContextVar('ctx', default=None)
pool = ProcessPoolExecutor(max_workers=2)

def task():
    print(f'inside pool process, ctx: {ctx.get()}')
    ctx.set('co co')
    return ctx.get()

async def execute():
    loop = asyncio.get_event_loop()
    ctx.set('yo yo')
    ctx_from_pool = await loop.run_in_executor(pool, task)
    ctx_from_async = ctx.get()
    print(f'ctx_from_async: {ctx_from_async}')
    print(f'ctx_from_pool: {ctx_from_pool}')
    ctx.set('bo bo')

def main():
    loop = asyncio.get_event_loop()
    loop.run_until_complete(asyncio.ensure_future(execute()))
    ctx_from_main = ctx.get()
    print(f'ctx_from_main: {ctx_from_main}')

main()

输出:

inside pool process, ctx: yo yo
ctx_from_async: yo yo
ctx_from_pool: co co
ctx_from_main: None

我的理解是,进程池所做的contextvars更改ctx.set('co co')不会传播到主进程的原因是,在分配任务时,使用了pickle来创建变量的副本,由于该更改是在变量的另一副本上进行而不是在主进程访问的副本上进行。但是,我对此并不完全确定,因为我对ProcessPoolExecutor没有太多经验。 有人可以再给它一些光吗?另外,如何在asyncio循环和进程池执行程序之间无缝操作contextvar?

0 个答案:

没有答案