当前位置: 首页 > 面试题库 >

从asyncio.Protocol.data_received调用协程

倪德业
2023-03-14
问题内容

这类似于在asyncio.Protocol.data_received中调用协程,但是我认为这值得一个新的问题。

我有一个像这样的简单服务器

loop.create_unix_server(lambda: protocol, path=serverSocket)

如果我这样做的话,效果很好

 def data_received(self, data):
    data = b'data reply'
    self.send(data)

我的客户得到答复。但是我无法让它与任何类型的asyncio呼叫一起使用。我尝试了以下所有方法,但没有一个起作用。

@asyncio.coroutine
def go(self):
    yield from asyncio.sleep(1, result = b'data reply')

def data_received(self, data):
    print('Data Received', flush=True)

    task = asyncio.get_event_loop().create_task(self.go())
    data = yield from asyncio.wait_for(task,10)
    self.send(data)

那个挂了并且什么也没打印(如果我data_received用我装饰的东西@asyncio.coroutine得到的不是从中得到的),好,我得到了使用yieldindata_received是不正确的。

如果我尝试一个新的事件循环(如下所示),则会挂起 run_until_complete

    loop = asyncio.new_event_loop()
    task = loop.create_task(self.go())
    loop.run_until_complete(task)
    data = task.result()
    self.send(data)

如果我使用Future,那也会挂在run_until_complete

@asyncio.coroutine
def go(self, future):
    yield from asyncio.sleep(1)
    future.set_result(b'data reply')

def data_received(self, data):
    print('Data Received', flush=True)

    loop = asyncio.new_event_loop()
    future = asyncio.Future(loop=loop)
    asyncio.async(self.go(future))
    loop.run_until_complete(future)
    data = future.result()
    self.send(data)

以下代码很接近,但是它立即返回,并且结果是type
asyncio.coroutines.CoroWrapper,这意味着该wait_for行随未完成的任务立即返回?

@asyncio.coroutine
def go(self):
    return(yield from asyncio.sleep(3, result = b'data reply'))

@asyncio.coroutine
def go2(self):
    task = asyncio.get_event_loop().create_task(self.go())
    res = yield from asyncio.wait_for(task, 10)
    return result

def data_received(self, data):
    print('Data Received', flush=True)

    data = self.go2()
    self.send(data)

我确实有点卡住,不胜感激一些关于看什么的指示。


问题答案:

您需要将协程添加到事件循环中,然后Future.add_done_callback在协程完成时使用来处理结果:

@asyncio.coroutine
def go(self):
    return(yield from asyncio.sleep(3, result = b'data reply'))

def data_received(self, data):
    print('Data Received', flush=True)

    task = asyncio.async(self.go()) # or asyncio.get_event_loop().create_task()
    task.add_done_callback(self.handle_go_result)

def handle_go_result(self, task):
    data = task.result()
    self.send(data)

data_received根本不允许直接调用协程,因为调用者不会尝试调用协程yield from,并且在内部创建/运行新的事件循环data_received将始终阻塞主事件循环,直到内部事件循环结束为止工作。

您只想通过主事件循环(asyncio.async/
loop.create_task())安排一些工作,并安排在工作完成后运行的回调(add_done_callback)。



 类似资料:
  • 使用Swoole协程时,可以使用下面的方法进行调试 GDB调试 进入 gdb gdb php test.php gdbinit (gdb) source /path/to/swoole-src/gdbinit 设置断点 例如 co::sleep 函数 (gdb) b zim_swoole_coroutine_util_sleep 打印当前进程的所有协程和状态 (gdb) co_list coro

  • 我正在尝试从 Java 7 调用科特林函数。我正在使用协程,这个被调用的函数正在挂起,例如: 我在版本 0.25.3 中使用了协程,我可以通过传递继续来模拟简单的 Java 回调样式 ,但是我使用的是Android,这意味着只使用Java 7。另一方面,简单的< code>Future太愚蠢了,因为我不想定期检查函数是否完成——我只想在函数完成时被调用。我真的希望避免添加新的库或许多额外的类/方法

  • 我刚刚在Codity遇到了一个任务,我找不到目标O(n)效率的解决方案;我的解决方案运行为O(n2)。如果有人能给我一个提示,告诉我如何让它运行得更快,我会非常高兴。这是任务。 给出了一个由N个整数组成的非空零索引数组A。 monotonic_pair是一对整数 (P, Q),使得 0 ≤ P ≤ Q 目标是找到指数相距最远的monotonic_pair。更准确地说,我们应该最大化Q-P值。只找到

  • 问题内容: 我想知道是否有可能实现这样的目标。 我有一个这样的游乐场: 我可以在中提供默认实现,但是如果需要默认实现中的所有内容以及其他内容,该怎么办? 它在某种程度上类似于es中的调用方法,可以满足实现每个属性等的要求。但是我看不到用实现相同的可能性。 问题答案: 我不知道您是否还在寻找答案,但是要做的方法是从协议定义中删除函数,将对象转换为对象,然后在其上调用方法: 由于某种原因,它仅在函数未

  • 我已经在互联网上闲逛了很长一段时间,我想知道如何在不打开不同端口的情况下一起使用BufferedReader和DataInputStream。我尝试过流式图像,但由于缓冲读取器存储了额外的字节,它创建了一个损坏的图像。当我尝试使用datainputstream.read()时,我无法轻松地读取整行文本。我的问题有什么解决办法吗?

  • 理解Go的函数调用协议对于研究其内部实现非常重要。这里将会介绍Go进行函数调用时的内存布局,参数传递和返回值的约定。正如C和汇编都是同一套约定所以能相互调用一样,Go和C以及汇编也是要满足某些约定才能够相互调用。 本章先从Go调用C和汇编的例子开始(非cgo方式),通过分析其实现学习Go的函数调用协议。然后将会研究go和defer关键字等神奇的魔法。接着会研究连续栈的实现,最后看一下闭包。 这一章