python - asyncio.subprocess 总是阻塞

标签 python python-3.x python-asyncio

我需要编写一些异步代码来运行子进程作为其任务的一部分。即使我使用 asyncio.subprocess 我的代码仍然阻塞。我的服务器看起来像这样:

import asyncio
import asyncio.subprocess
import websockets

async def handler(websocket, path):
    while True:
        data = await websocket.recv()
        print('I received a message')
        player = await asyncio.create_subprocess_exec(
            'sleep', '5',
            stdin=asyncio.subprocess.DEVNULL,
            stdout=asyncio.subprocess.DEVNULL,
            stderr=asyncio.subprocess.DEVNULL)
        await player.wait()
        print('Finished waiting')

server = websockets.serve(handler, '0.0.0.0', '8000')
asyncio.get_event_loop().run_until_complete(server)
asyncio.get_event_loop().run_forever()

还有一个非常基本的客户端:

导入异步 导入网络套接字

async def client():
    async with websockets.connect('ws://localhost:8000') as websocket:
        for i in range(5):
            await websocket.send('message')
            await asyncio.sleep(0.5)

asyncio.get_event_loop().run_until_complete(client())

我希望输出如下所示:

I received a message
I received a message
I received a message
I received a message
I received a message
Finished waiting
Finished waiting
Finished waiting
Finished waiting
Finished waiting

但我得到的是这个:

I received a message
Finished waiting
I received a message
Finished waiting
I received a message
Finished waiting
I received a message
Finished waiting
I received a message
Finished waiting

每行“我收到一条消息”后等待 5 秒。

最佳答案

awaitplayer.wait()行不会阻塞其他异步操作,而是等待5秒!

如果您不想等待响应,请尝试使用ensure_future():

# add:
async def wait_for_player(player, path):
    print("Waiting...", path)
    await player.wait()
    print("Done", path)

# and replace await player.wait() with:
asyncio.ensure_future(wait_for_player(player, path))

实际上,您也可以将 create_subprocess_exec() 移至 wait_for_player()


要查看您的代码没有阻塞,请尝试以下操作:

客户:

import asyncio

import websockets


async def client(n):
    async with websockets.connect('ws://localhost:8000/{}/'.format(n)) as websocket:
        print(n, "start")
        for i in range(5):
            print(n, i)
            await websocket.send('message')
            await asyncio.sleep(0.5)
    print(n, "done")


tasks = [client(i) for i in range(5)]
asyncio.get_event_loop().run_until_complete(asyncio.wait(tasks))

服务器:

import asyncio
import asyncio.subprocess

import random
import websockets


async def handler(websocket, path):
    try:
        while True:
            data = await websocket.recv()
            pause = random.randint(1, 5)
            print('I received a message', path, "Pausing:", pause)
            player = await asyncio.create_subprocess_exec(
                'sleep', str(pause),
                stdin=asyncio.subprocess.DEVNULL,
                stdout=asyncio.subprocess.DEVNULL,
                stderr=asyncio.subprocess.DEVNULL)
            await player.wait()
            print('Finished waiting', path)
    except websockets.ConnectionClosed:
        print("Connection closed!", path)


server = websockets.serve(handler, '0.0.0.0', '8000')
asyncio.get_event_loop().run_until_complete(server)
asyncio.get_event_loop().run_forever()

关于python - asyncio.subprocess 总是阻塞,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42584769/

相关文章:

python - 是否可以限制异步中同时运行的协程数量?

python - 将 Python Cement 与 asyncio 相结合

python - 如何在log.html 和output.xml 中添加一些ROBOT Framework 测试统计的外部链接?

python-3.x - python pyinstaller 未找到名为 "cairo"的库

python - `list[]` 之类的东西在 Python 中引发 `SyntaxError` 是有原因的吗?

python - Python 3 中的 For 循环

python - 线程模块的引用未被 gc 删除

python - python asyncio 中的协议(protocol)工厂有什么要求?

python - 在 python 中打印打开文件的前 400 个字符

python - 使用pyjq解析多个json值,用逗号分隔