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__
中.
我有一个基本上做两件事的程序:
打开一个 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__
中.