Python 进程阻塞应用程序的其余部分

Python Process blocking the rest of application

我有一个基本上做两件事的程序:

打开一个 websocket 并继续监听消息并在永远循环中开始视频流。

我曾尝试使用多进程来管理这两件事,但其中一件阻止了另一件 运行ning。

该应用是

if __name__ == '__main__':

    loop = asyncio.get_event_loop()
    loop.run_until_complete(start_client())


async def start_client():
        async with WSClient() as client:
            
            pass

class WSClient:
    async def __aenter__(self):
        
        async with websockets.connect(url,max_size= None) as websocket:
            self.websocket = websocket
            await self.on_open() ## it goes
            p = Process(target = init(self)) # This is the streaming method  
            p.start()

            async for message in websocket:
                await on_message(message, websocket) ## listen for websocket messages
            
         
        return self

初始化方法是

def init(ws):
    logging.info('Firmware Version: ' + getVersion())
    
    startStreaming(ws)
    return

基本上 startStreaming 中有一个无限循环。

在此配置中,流开始但未调用 websocket 的 on_message,因为 Process 函数冻结了应用程序的其余部分。

我怎样才能 运行 这两种方法?

谢谢

在您的代码中,您告诉 multiprocessing.Process 获取 init 返回的函数并在新进程中调用它。您想要的是进程调用 init 本身(带有参数)。方法如下:

p = Process(target=init, args=(self,))

我必须注意,您正在将一个异步 websocket 对象传递给您的 init 函数。这可能会中断,因为 asyncio 的东西通常不打算在两个线程中使用,更不用说两个进程了。除非您以某种方式在新进程中重新创建 websocket 对象并在那里创建一个新循环,否则您实际上要寻找的是如何 create an asyncio task.

假设startStreaming已经是一个异步函数,你应该把init函数改成这样:

async def init(ws):  # note the async
    logging.info('Firmware Version: ' + getVersion())
    await startStreaming(ws)  # note the await
    return

并将创建和启动流程的行更改为:

asyncio.create_task(init(self))

这将 运行 您的 startStreaming 在新任务中发挥作用,同时您也(基本上)同时阅读收到的消息。

另外,我不确定你想用异步上下文管理器做什么,因为一切都可能只是在一个普通的异步函数中。如果您有兴趣将其用于学习目的,我建议您查看 contextlib.asynccontextmanager 并将您的消息读取代码放在 start_client 中的 async with 语句中,而不是 __aenter__ 中.