【问题标题】:Python Process blocking the rest of applicationPython进程阻塞应用程序的其余部分
【发布时间】:2021-10-20 09:37:12
【问题描述】:

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

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

我试图使用多进程来管理这两件事,但一个阻止另一个运行。

应用是

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

init方法是

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

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

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

如何同时运行这两种方法?

谢谢

【问题讨论】:

    标签: python python-multiprocessing


    【解决方案1】:

    在您的代码中,您告诉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__ 中。

    【讨论】:

    • 非常感谢,我找到了另一个使用线程的解决方案,但你的似乎更清晰,因为这样我将有 2 个异步任务一起运行。我需要将 ws 对象传递给 init 函数,因为我需要在 startStreaming 方法中发送想法。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-10-14
    • 2021-10-14
    • 2018-01-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-15
    相关资源
    最近更新 更多