这是来自asyncio tutotial的基本tcp服务器:
import asyncio
class EchoServerClientProtocol(asyncio.Protocol):
def connection_made(self, transport):
peername = transport.get_extra_info('peername')
print('Connection from {}'.format(peername))
self.transport = transport
def data_received(self, data):
message = data.decode()
print('Data received: {!r}'.format(message))
print('Send: {!r}'.format(message))
self.transport.write(data)
print('Close the client socket')
self.transport.close()
loop = asyncio.get_event_loop()
# Each client connection will create a new protocol instance
coro = loop.create_server(EchoServerClientProtocol, '127.0.0.1', 8888)
server = loop.run_until_complete(coro)
# Serve requests until CTRL+c is pressed
print('Serving 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()
像所有(我发现)其他例子一样,它使用阻塞loop.run_forever() 我如何开始倾听服务器并在当时做其他事情? 我试图在一个函数中外包启动服务器并使用asyncio.async()启动此函数,但没有成功。 我在这里缺少什么?
答案 0 :(得分:1)
您可以在调用loop.run_forever()
之前安排多个并发的asyncio任务。
@asyncio.coroutine
def other_task_coroutine():
pass # do something
start_tcp_server_task = loop.create_task(loop.create_server(
EchoServerClientProtocol, '127.0.0.1', 8888))
other_task = loop.create_task(other_task_coroutine())
self.run_forever()
当您致电loop.create_task(loop.create_server())
或loop.create_task(other_task_coroutine())
时,实际上没有执行:创建协程对象并将其包装在任务中(将任务视为shell和coroutine将在任务中执行的代码实例)。任务在创建时安排在循环中。
循环首先执行start_tcp_server_task
(因为它是第一次调度),直到阻塞IO事件挂起或被动套接字准备好侦听传入连接。
您可以将asyncio视为在一个CPU上运行的不可抢占的调度程序:一旦第一个任务中断或完成,第二个任务将被执行。因此,当执行一个任务时,另一个任务必须等到正在运行的任务完成或产生(或“等待”使用Python 3.5)。 “让步”(yield from client.read()
)或“等待”(await client.read()
)意味着任务将手交给循环的调度程序,直到client.read()
可以执行(数据在套接字上可用) )。
一旦任务将控制权交还给循环,它就可以安排其他待处理任务,处理传入事件并安排等待这些事件的任务。一旦没有什么可做的,循环将执行进程的唯一阻塞调用:休眠直到内核通知它事件已准备好被处理。
在此上下文中,您必须了解在使用asyncio时,进程中运行的所有内容都必须异步运行,以便循环可以完成其工作。您不能在循环中使用多处理对象。
请注意,asyncio.async(coroutine(), loop=loop)
相当于loop.create_task(coroutine())
。
答案 1 :(得分:1)
此外,您可以考虑在执行程序中运行您想要的内容。 例如。
coro = loop.create_server(EchoServerClientProtocol, '127.0.0.1', 8888)
server = loop.run_until_complete(coro)
async def execute(self, loop):
await loop.run_in_executor(None, your_func_here, args:
asyncio.async(execute(loop))
loop.run_forever()
执行程序将在执行程序中运行您想要的任何功能,执行程序不会阻止您的服务器。