python - 使用 asyncio 的非阻塞 I/O

标签 python python-3.x pygame python-asyncio

我正在尝试使用 Pygame 和 asyncio 编写网络游戏,但我不知道如何避免挂起读取。这是我的客户代码:

@asyncio.coroutine
def handle_client():
    print("Connected!")
    reader, writer = yield from asyncio.open_connection('localhost', 8000)
    while True:
        mouse_up = False
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                sys.exit()                
            elif event.type == pygame.MOUSEBUTTONUP:
                mouse_up = True

        if mouse_up:
            print("Writing")
            writer.write(b"Mouse up")
        print("Waiting to read")
        line = yield from reader.read(2**12)
        print(line.decode())

    writer.close()

这卡在 line = yield from reader.read(2**12) 行。我之前认为 asyncio 的意义在于它是非阻塞的,因此如果没有任何数据要读取,它就会继续执行。我现在看到情况并非如此。

如何将 asyncio 网络代码与 Pygame 绘图和事件代码集成?

最佳答案

yield from的要点是将执行切换到asyncio的事件循环阻塞当前协程,直到有结果。要在不阻塞当前协程的情况下安排任务,可以使用 asyncio.async()

在不阻塞 pygame 循环的情况下打印已读取的数据:

@asyncio.coroutine
def read(reader, callback):
    while True:
        data = yield from reader.read(2**12)
        if not data: # EOF
            break
        callback(data)

@asyncio.coroutine
def echo_client():
    reader, ...
    chunks = []
    asyncio.async(read(reader, chunks.append))
    while True:
        pygame.event.pump() # advance pygame event loop
        ...
        if chunks: # print read-so-far data
            print(b''.join(chunks).decode())
            del chunks[:]
        yield from asyncio.sleep(0.016) # advance asyncio loop

while 循环内不应有阻塞调用。

read()sleep() 协程在同一个线程中并发运行(显然你也可以同时运行其他协程)。

关于python - 使用 asyncio 的非阻塞 I/O,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27676954/

相关文章:

python - 使用 Python 改进用于 AR 应用的视频两帧之间的单应性估计

用于发布多部分/表单数据编码数据的 Python 标准库

python - 使用selenium无法通过id找到元素

python - 在 pygame 中使用 matplotlib

python - Gtk3 用另一个小部件替换子小部件

python - SQLITE 数据库表差异

python - json.dump 不写入文件

python - 传递导入错误 : ModuleNotFoundError: No module named '...'

Python:类型错误:文本必须是 unicode 或字节

python - 列表中敌人之间的 Pygame/Python 测试?