python - 协程上的 Python asyncio 块,但不是 websockets
问题描述
考虑以下代码:
async def remote_data_retriever():
remote = Remote(sock_path)
while True:
Cached.update_global(remote.get_global())
await asyncio.sleep(RTR_RETR_INTERVAL)
async def on_message(websocket, path):
async for message in websocket:
data = Cached.get_global()
await websocket.send(json.dumps(data.__dict__))
if __name__ == '__main__':
ssl_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2)
ssl_context.load_cert_chain(RTR_CERT_PATH)
app_server = websockets.serve(on_message, RTR_LISTEN_HOST, RTR_LISTEN_PORT, ssl=ssl_context)
try:
asyncio.get_event_loop().run_until_complete(app_server)
print('1')
asyncio.get_event_loop().run_until_complete(remote_data_retriever())
print('2')
asyncio.get_event_loop().run_forever()
except Exception as e:
print(e)
此代码将打印“1”,然后从不打印“2”。如何正确安排协程,使其不会阻塞以下调用
asyncio.get_event_loop().run_until_complete(remote_data_retriever())
?
解决方案
run_until_complete(task)
立即开始任务并等待其真正结束,而不是await
. 但是您的第二个任务使用while True
永无止境。
您应该将任务添加到循环使用create_task(task)
并稍后使用run_forever()
.
asyncio.get_event_loop().create_task(app_server)
print('1')
asyncio.get_event_loop().create_task(remote_data_retriever())
print('2')
asyncio.get_event_loop().run_forever()
然后这两个任务将在一个循环中运行,await
并将停止一个任务以启动另一个任务。
每个人都可以运行的示例代码
import asyncio
async def task_1():
number = 0
while True:
number += 1
print('task1', number)
await asyncio.sleep(1)
async def task_2():
number = 0
while True:
number += 1
print('task2', number)
await asyncio.sleep(1)
if __name__ == '__main__':
loop = asyncio.get_event_loop()
try:
loop.create_task(task_1())
print('1')
loop.create_task(task_2())
print('2')
loop.run_forever()
except Exception as e:
print(e)
推荐阅读
- redhat - RHEL 7.9 Maipo 中没有可用的软件包 llvm-toolset-7.0
- openhardwaremonitor - 使用openhardwaremonitor dll问题
- javascript - TypeError: setCartCount 不是一个函数 - React Hooks - Redux
- javascript - 如何设置子对象的状态
- python - 如何矢量化这个循环?
- javascript - 如何计算文本区域中的字符?
- javascript - 如何根据每个对象内的数组从对象数组中返回某些对象?
- shell - 为什么我的用于创建拆分窗口 tmux 会话的 shell 脚本不起作用
- javascript - rShiny 自定义 css javascript 滑块 - 如何从中获取值?
- acme - 使用 step-ca 作为中间 ca,并带有父 CA 提供的证书