Изменения, внесенные в контекстные переменные в пуле процессов, не распространяются на основной процесс, выполняющий цикл asyncio - PullRequest
0 голосов
/ 25 мая 2019

Ниже приведен фрагмент кода, который я запустил:

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

Насколько я понимаю, причина изменения контекстных переменных ctx.set('co co'), сделанная пулом процессов, чтобы не распространяться на основной процесс, заключается в том, что при назначении задачи копия переменных создается с использованием pickle, из-за которого было сделано изменение другая копия переменной, а не та, к которой обращается основной процесс. Однако я не совсем уверен в этом, так как у меня нет большого опыта работы с ProcessPoolExecutor. Может ли кто-то пролить дополнительный свет на то же самое? Кроме того, что можно сделать для плавного манипулирования контекстными переменными в цикле asyncio и в пуле процессов?

...