带有asyncio的非阻塞I/O.

rlm*_*lms 19 python pygame python-3.x 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()
Run Code Online (Sandbox Code Playgroud)

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

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

jfs*_*jfs 9

关键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
Run Code Online (Sandbox Code Playgroud)

while循环内应该没有阻塞调用.

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

  • @Anna:这是Python 3.4代码。自 Python 3.5 起,`async()` 函数已被弃用。您可以使用“create_task()”,或者如果它不可用,则使用“ensure_future()”。https://docs.python.org/3/library/asyncio-task.html#asyncio.create_task (2认同)

小智 7

您可以将阻塞任务"转换"为非阻塞任务.

我建议:https://docs.python.org/3/library/asyncio-eventloop.html#executor.

我有一个功能,听取一个Twitter提要,功能"提",我在执行器中运行它,所以如果它挂起,它不会阻止其他任务.

@asyncio.coroutine
def boucle_deux():
#faire attendre la boucle si pas bcp de mots
    while True:
        print("debut du deux")
        value = t.next()
        future2 = loop.run_in_executor(None, mention, "LQNyL2xvt9OQMvje7jryaHkN8",
                                       "IRJX6S17K44t8oiVGCjrj6XCVKqGSX9ClfpGpfC467rajqePGb",
                                       "2693346740-km3Ufby8r9BbYpyzcqwiHhss22h4YkmnPN4LnLM",
                                       "53R8GAAncFJ1aHA1yJe1OICfjqUbqwcMR38wSqvbzsQMB", 23, value)
        response2 = yield from future2
        yield from asyncio.sleep(5)
        print("fin du deux")

asyncio.Task(boucle_deux())
Run Code Online (Sandbox Code Playgroud)

  • 执行程序的目的是在单独的线程中运行缓慢或阻塞操作(进程由内核的调度程序抢占).StreamReader.read()永远不会阻塞. (5认同)