Python—将多处理与asyncio相结合有时才有效

Python—将多处理与asyncio相结合有时才有效,python,multiprocessing,python-asyncio,python-multiprocessing,Python,Multiprocessing,Python Asyncio,Python Multiprocessing,我想结合异步io和多处理,因为我有一个任务,其中一部分是io绑定的,另一部分是cpu绑定的。我第一次尝试使用loop.run_in_executor(),但可能无法让它工作。相反,我创建了两个进程,其中一个使用asyncio,另一个不使用 代码是这样的,我有一个类,有一些非阻塞函数和一个阻塞函数。我有一个asyncio.Queue在非阻塞部分之间传递信息,还有一个multiprocessing.Queue在非阻塞函数和阻塞函数之间传递信息 import multiprocessing as mp

我想结合异步io和多处理,因为我有一个任务,其中一部分是io绑定的,另一部分是cpu绑定的。我第一次尝试使用loop.run_in_executor(),但可能无法让它工作。相反,我创建了两个进程,其中一个使用asyncio,另一个不使用

代码是这样的,我有一个类,有一些非阻塞函数和一个阻塞函数。我有一个asyncio.Queue在非阻塞部分之间传递信息,还有一个multiprocessing.Queue在非阻塞函数和阻塞函数之间传递信息

import multiprocessing as mp
from concurrent.futures import ProcessPoolExecutor
import asyncio
import time


class TestClass:
    def __init__(self):
        m = mp.Manager()
        self.blocking_queue = m.Queue()

    async def run(self):
        loop = asyncio.get_event_loop()
        self.non_blocking_queue = asyncio.Queue() # asyncio Queue must be declared within event loop
        task1 = loop.create_task(self.non_blocking1())
        task2 = loop.create_task(self.non_blocking2())
        task3 = loop.create_task(self.print_msgs())
        await asyncio.gather(task1, task2)
        task3.cancel()

    def blocking(self):
        i = 0
        while i < 5:
            time.sleep(0.6)
            i += 1
            print("Blocking ", i)
            line = self.blocking_queue.get()
            print("Blocking: ", line)
        print("blocking done")

    async def non_blocking1(self):
        for i in range(5):
            await self.non_blocking_queue.put("Hello")
            await asyncio.sleep(0.4)

    async def non_blocking2(self):
        for i in range(5):
            await self.non_blocking_queue.put("World")
            await asyncio.sleep(0.5)

    async def print_msgs(self):
        while True:
            line = await self.non_blocking_queue.get()
            self.blocking_queue.put(line)
            print(line)


test_class = TestClass()
with ProcessPoolExecutor() as pool:
    pool.submit(test_class.blocking)
    pool.submit(asyncio.run(test_class.run()))
print("done")
将多处理导入为mp
从concurrent.futures导入ProcessPoolExecutor
导入异步
导入时间
类TestClass:
定义初始化(自):
m=mp.Manager()
self.blocking_queue=m.queue()
异步def运行(自):
loop=asyncio.get\u event\u loop()
self.non_blocking_queue=asyncio.queue()#必须在事件循环中声明asyncio队列
task1=loop.create_任务(self.non_blocking1())
task2=loop.create_任务(self.non_blocking2())
task3=loop.create_任务(self.print_msgs())
等待asyncio.gather(任务1、任务2)
任务3.取消()
def阻塞(自):
i=0
当我<5时:
睡眠时间(0.6)
i+=1
打印(“分块”,i)
line=self.blocking_queue.get()
打印(“分块:”,行)
打印(“阻止完成”)
异步def非_阻塞1(自):
对于范围(5)中的i:
等待自我。非阻塞队列。放置(“你好”)
等待异步睡眠(0.4)
异步def非_阻塞2(自):
对于范围(5)中的i:
等待自我。非阻塞队列。放置(“世界”)
等待异步睡眠(0.5)
异步def打印(自我):
尽管如此:
line=wait self.non_blocking_queue.get()
self.blocking_queue.put(行)
打印(行)
test_class=TestClass()
将ProcessPoolExecutor()作为池:
提交(测试类阻塞)
pool.submit(asyncio.run(test_class.run()))
打印(“完成”)
大约有一半的时间,我运行这个,它工作良好,并打印出文本在阻塞和非阻塞队列。另一半只打印非阻塞队列的结果。看起来阻塞过程根本没有启动。这不是每隔一段时间就会发生的。它可能连续工作五次,然后不连续工作五次

什么可能导致这样的问题?使用多处理和异步IO,我可以用哪种更好的方法来实现这一点?

在另一个进程的“内部”运行异步任务,例如:

def runfn(fn):
返回asyncio.run(fn())
将ProcessPoolExecutor()作为池:
提交(测试类阻塞)
提交(runfn,test_class.run)

大概asyncio/任务内部存在某种状态,需要保持一致,或者在另一个进程中运行时出现中断

看看我不明白为什么这会产生不同。但确实如此。现在每次都能用。非常感谢你。