我正在尝试使用asyncio将Python代码中基于回调的同步流转换为a同步流。 基本上,代码与TCP/UNIX套接字交互很多。它从套接字读取数据,操纵它做出决策,并将数据写回另一端。这是在多个套接字上同时进行的,并且数据在上下文之间共享,以便有时做出决策。在
EDIT::当前的代码主要基于注册一个回调到一个特定套接字的中心实体,并在相关套接字可读时让该实体运行回调(类似于“当该套接字有数据要读取时调用此函数”)。一旦回调被调用,就会发生一系列的事情,最终在新数据可用时注册一个新的回调。中心实体对所有注册的套接字运行select,以确定应该调用哪些回调。在
我试图做到这一点,而不是重构我的整个代码,并使它尽可能无缝的程序员-所以我试着这样想-所有的代码都应该像今天一样运行-但是每当当前代码做接收插座()以获取新数据-该进程将执行其他任务。当read返回时,它应该返回到使用它获得的新数据处理来自同一点的数据。在
为此,我编写了一个名为AsyncSocket的新类,它与asyncIO的IO流交互,并将Async/await语句几乎完全放在其中—我认为我将在类中实现recv方法,使其在我的代码中看起来像“常规IO套接字”。 到目前为止,这是我对A-sync编程应该允许什么的理解。在
现在是问题:
我的代码等待客户机连接-当它连接时,允许每个客户机的上下文从它自己的连接读写。 为了澄清问题,我简化为以下流程:
class AsyncSocket():
def __init__(self,reader,writer):
self.reader = reader
self.writer = writer
def recv(self,numBytes):
print("called recv!")
data = self.read_mitigator(numBytes)
return data
async def read_mitigator(self,numBytes):
print("Awaiting of AsyncSocket.reader.read")
data = await self.reader.read(numBytes)
print("Done Awaiting of AsyncSocket.reader.read data is %s " % data)
return data
def mit2(aSock):
return mit3(aSock)
def mit3(aSock):
return aSock.recv(100)
async def echo_server(reader, writer):
print ("New Connection!")
aSock = AsyncSocket(reader,writer) # create a new A-sync socket class and pass it on the to regular code
while True:
data = await some_func(aSock) # this would eventually read from the socket
print ("Data read is %s" % (data))
if not data:
break
writer.write(data) # echo everything back
async def main(host, port):
server = await asyncio.start_server(echo_server, host, port)
await server.serve_forever()
asyncio.run(main('127.0.0.1', 5000))
mit2()和mit3()是同步函数,它们在返回主客户机循环之前处理返回的数据,但这里我只是将它们用作空函数。 当我使用一些\u func()的实现时,问题就开始了。在
一个传递实现(编辑:有点管用),但仍然存在以下问题:
^{pr2}$而读取数据并对其执行某些操作(如在返回前添加后缀)时,会抛出一个错误:
def some_func(aSock):
try:
return (mit2(aSock) + "something") # doesn't work
except:
print("Error!!!!")
这个错误(据我所知)意味着它没有真正做它应该做的事情:
New Connection!
called recv!
/Users/user/scripts/asyncServer.py:36: RuntimeWarning: coroutine 'AsyncSocket.read_mitigator' was never awaited
return (mit2(aSock) + "something") # doesn't work
RuntimeWarning: Enable tracemalloc to get the object allocation traceback
Error!!!!
Data read is None
回音服务器显然不工作了。 显然,我的代码看起来更像是选项2,其中一些函数中有很多东西,mit2()和mit3(),但我不能让它工作。我在使用asyncio/async/await方面是一个相当新的概念,那么我遗漏了什么(我想是相当基本的概念)?在
此代码无法按预期工作:
不能从sync函数调用异步函数并获得结果,必须等待它,这样可以确保在数据尚未准备好的情况下返回事件循环。异步和同步代码之间的这种不匹配有时被称为function color问题。在
由于您的代码已经在使用非阻塞套接字和事件循环,所以将其移植到asyncio的一个好方法可能是首先切换到asyncio事件循环。您可以使用事件循环方法,如^{} 请求数据:
^{pr2}$一旦程序在该模式下工作,就可以开始转到协同程序,这样代码就可以看起来像同步代码,但工作方式完全相同:
下一步可以消除
make_socket
并切换到asyncio streams。在相关问题 更多 >
编程相关推荐