如何更正 data_received 中的 asyncio yield
How to correct asyncio yield from in data_received
我会在 data_received 函数中向数据库发出异步请求,但我不知道该怎么做。我用 asyncio.sleep(2) 编写了简单的 HTTPServer,但它不起作用。
import time
import asyncio
class HTTPServer:
def connection_made(self, transport):
self.transport = transport
pass
def connection_lost(self, exc):
pass
def eof_received(self):
pass
@asyncio.coroutine
def data_received(self, data):
try:
#time.sleep(2)
yield from asyncio.sleep(2)
body = "Hello <br/>\n"
response = 'HTTP/1.1 {status}\r\n'.format(status="200")
response += 'Content-Length: {size}\r\n'.format(size=len(body))
response += 'Content-Type: text/html; charset=utf-8\r\n'.format(size=len(body))
response += 'Connection: close\r\n'.format(size=len(body))
response += '\r\n'
response += body
self.transport.write(response.encode('utf-8'))
except e:
print (e)
self.transport.close()
loop = asyncio.get_event_loop()
print ('Start server on 0.0.0.0:8080')
asyncio.ensure_future(loop.create_server(
lambda: HTTPServer(),
'0.0.0.0', 8080
))
try:
loop.run_forever()
pass
except KeyboardInterrupt:
loop.stop()
我注释行 @asyncio.coroutine 并从 asyncio.sleep(2) 中产生,它是有效的。我添加 time.sleep(2) 而不是 asyncio.sleep(2),这是有效的。但是异步不起作用。
我做错了什么?
您正在使用的 "Protocol" 来自(引用文档):
18.5.4. Transports and protocols (callback based API)
正如文档明确指出的那样,它是一个 "callback based API",它调用普通方法,您无法更改它,因此将 data_received
包装在“@asyncio.coroutine”中不行。
但是有一个基于协程的API,这是文档的下一章:
18.5.5. Streams (coroutine based API)
使用基于 API 的协程重写您的示例,您将得到:
import asyncio
async def request_handler(reader, writer):
await asyncio.sleep(2)
data = await reader.read(100)
message = data.decode()
addr = writer.get_extra_info('peername')
print("Received %r from %r" % (message, addr))
body = "Hello <br/>\n"
response = 'HTTP/1.1 {status}\r\n'.format(status="200")
response += 'Content-Length: {size}\r\n'.format(size=len(body))
response += 'Content-Type: text/html; charset=utf-8\r\n'.format(size=len(body))
response += 'Connection: close\r\n'.format(size=len(body))
response += '\r\n'
response += body
writer.write(response.encode('utf-8'))
await writer.drain()
writer.close()
loop = asyncio.get_event_loop()
coro = asyncio.start_server(request_handler, '127.0.0.1', 8080, loop=loop)
server = loop.run_until_complete(coro)
print('Start server on {}'.format(server.sockets[0].getsockname()))
try:
loop.run_forever()
except KeyboardInterrupt:
pass
# Close the server
server.close()
loop.run_until_complete(server.wait_closed())
loop.close()
请注意,如果您使用的是 Python 3.5,则可以像我一样使用 async def
和 await
而不是 @asyncio.coroutine
和 yield from
。
我会在 data_received 函数中向数据库发出异步请求,但我不知道该怎么做。我用 asyncio.sleep(2) 编写了简单的 HTTPServer,但它不起作用。
import time
import asyncio
class HTTPServer:
def connection_made(self, transport):
self.transport = transport
pass
def connection_lost(self, exc):
pass
def eof_received(self):
pass
@asyncio.coroutine
def data_received(self, data):
try:
#time.sleep(2)
yield from asyncio.sleep(2)
body = "Hello <br/>\n"
response = 'HTTP/1.1 {status}\r\n'.format(status="200")
response += 'Content-Length: {size}\r\n'.format(size=len(body))
response += 'Content-Type: text/html; charset=utf-8\r\n'.format(size=len(body))
response += 'Connection: close\r\n'.format(size=len(body))
response += '\r\n'
response += body
self.transport.write(response.encode('utf-8'))
except e:
print (e)
self.transport.close()
loop = asyncio.get_event_loop()
print ('Start server on 0.0.0.0:8080')
asyncio.ensure_future(loop.create_server(
lambda: HTTPServer(),
'0.0.0.0', 8080
))
try:
loop.run_forever()
pass
except KeyboardInterrupt:
loop.stop()
我注释行 @asyncio.coroutine 并从 asyncio.sleep(2) 中产生,它是有效的。我添加 time.sleep(2) 而不是 asyncio.sleep(2),这是有效的。但是异步不起作用。
我做错了什么?
您正在使用的 "Protocol" 来自(引用文档):
18.5.4. Transports and protocols (callback based API)
正如文档明确指出的那样,它是一个 "callback based API",它调用普通方法,您无法更改它,因此将 data_received
包装在“@asyncio.coroutine”中不行。
但是有一个基于协程的API,这是文档的下一章:
18.5.5. Streams (coroutine based API)
使用基于 API 的协程重写您的示例,您将得到:
import asyncio
async def request_handler(reader, writer):
await asyncio.sleep(2)
data = await reader.read(100)
message = data.decode()
addr = writer.get_extra_info('peername')
print("Received %r from %r" % (message, addr))
body = "Hello <br/>\n"
response = 'HTTP/1.1 {status}\r\n'.format(status="200")
response += 'Content-Length: {size}\r\n'.format(size=len(body))
response += 'Content-Type: text/html; charset=utf-8\r\n'.format(size=len(body))
response += 'Connection: close\r\n'.format(size=len(body))
response += '\r\n'
response += body
writer.write(response.encode('utf-8'))
await writer.drain()
writer.close()
loop = asyncio.get_event_loop()
coro = asyncio.start_server(request_handler, '127.0.0.1', 8080, loop=loop)
server = loop.run_until_complete(coro)
print('Start server on {}'.format(server.sockets[0].getsockname()))
try:
loop.run_forever()
except KeyboardInterrupt:
pass
# Close the server
server.close()
loop.run_until_complete(server.wait_closed())
loop.close()
请注意,如果您使用的是 Python 3.5,则可以像我一样使用 async def
和 await
而不是 @asyncio.coroutine
和 yield from
。