python 中的 asyncio 是否支持基于协程的 UDP 网络 API?

2024-01-13

我正在浏览 pythonasyncio今晚我正在查看模块文档,为我的一个课程项目寻找一些想法,但我很快发现 python 标准中可能缺少功能aysncio module.

如果你查看文档,你会发现有一个基于回调的 API 和一个基于协程的 API。回调 API 可以用于构建 UDP 和 TCP 应用程序,而协程 API 看起来只能用于构建 TCP 应用程序,因为它使用了流式 API。

这对我来说确实是一个问题,因为我正在寻找一个基于协程的 UDP 网络 API,尽管我确实发现了asyncio支持基于低级协程的套接字方法,例如sock_recv https://docs.python.org/3/library/asyncio-eventloop.html#asyncio.AbstractEventLoop.sock_recv and sock_sendall https://docs.python.org/3/library/asyncio-eventloop.html#asyncio.AbstractEventLoop.sock_sendall,但是 UDP 网络的关键 API,recvfrom and sendto不在那里。

我想做的是编写一些代码,例如:

async def handle_income_packet(sock):
    await data, addr = sock.recvfrom(4096)
    # data handling here...
    await sock.sendto(addr, response)

我知道这可以使用回调 API 等效地实现,但这里的问题是回调不是协程而是常规函数,因此在其中您无法将控制权交还给事件循环并保留函数执行状态。

看看上面的代码,如果我们需要在数据处理部分做一些阻塞IO操作,那么只要我们的IO操作也在协程中完成,那么在协程版本中就不会有问题:

async def handle_income_packet(sock):
    await data, addr = sock.recvfrom(4096)
    async with aiohttp.ClientSession() as session:
        info = await session.get(...)
    response = generate_response_from_info(info)
    await sock.sendto(addr, response)

只要我们使用await事件循环将从该点开始控制流来处理其他事情,直到 IO 完成。但遗憾的是这些代码是not目前可用,因为我们没有协程版本socket.sendto and socket.recvfrom in asyncio.

我们可以使用传输协议回调 API 来实现这一点:

class EchoServerClientProtocol(asyncio.Protocol):
    def connection_made(self, transport):
        peername = transport.get_extra_info('peername')
        self.transport = transport

    def data_received(self, data):
        info = requests.get(...)
        response = generate_response_from_info(info)
        self.transport.write(response)
        self.transport.close()

我们不可以await那里有一个协程,因为回调不是协程,并且使用像上面这样的阻塞 IO 调用会阻止回调中的控制流,并阻止循环处理任何其他事件,直到 IO 完成

另一个推荐的实现想法是创建一个Future对象在data_received函数,将其添加到事件循环中,并将任何需要的状态变量存储在 Protocol 类中,然后显式地将控制权返回给循环。虽然这可行,但它确实创建了许多复杂的代码,而在协程版本中,它们根本不需要。

Also here https://www.pythonsheets.com/notes/python-asyncio.html#simple-asyncio-udp-echo-server我们有一个使用非阻塞套接字的示例add_reader用于处理 UDP 套接字。但与 coroutine-version 的几行代码相比,代码看起来仍然很复杂。

我想说的一点是,协程是一种非常好的设计,可以利用单线程中的并发能力,同时还具有非常简单的设计模式,可以节省脑力和不必要的代码行,但关键部分是要获得我们确实缺乏它适用于 UDP 网络asyncio标准库。

大家对此有何看法?

另外,如果对支持此类 UDP 网络 API 的 3rd 方库有任何其他建议,我将非常感谢我的课程项目。我发现Bluelet https://github.com/sampsyo/bluelet很像这样的事情,但似乎并没有积极维护。

edit:

看来这PR https://github.com/python/asyncio/pull/321确实实现了这个功能,但被拒绝了asyncio开发商。开发者声称所有功能都可以使用来实现create_datagram_endpoint(),协议传输 API。但正如我上面所讨论的,在许多用例中,与使用回调 API 相比,协程 API 具有简单性的优势,但不幸的是我们在 UDP 中没有这些。


不提供基于流的 API 的原因是因为流提供orderingUDP 通信本质上是无序的,因此两者从根本上是不兼容的。

但这并不意味着您不能从回调中调用协程 - 事实上这非常简单!从EchoServerProtocol example https://docs.python.org/3/library/asyncio-protocol.html#udp-echo-server, 你可以这样做:

def datagram_received(self, data, addr):
    loop = asyncio.get_event_loop()
    loop.create_task(self.handle_income_packet(data, addr))

async def handle_income_packet(self, data, addr):
    # echo back the message, but 2 seconds later
    await asyncio.sleep(2)
    self.transport.sendto(data, addr)

Here datagram_received开始你的handle_income_packet可以自由等待任意数量的协程的协程。由于协程在“后台”运行,因此事件循环在任何时候都不会被阻塞,并且datagram_received立即返回,正如预期的那样。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

python 中的 asyncio 是否支持基于协程的 UDP 网络 API? 的相关文章

  • App Engine 上的 Django 与 webapp2 [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • 如何在 Pandas Python 中按 id 对行进行排名

    我有一个像这样的数据框 id points1 points2 1 44 53 1 76 34 1 63 66 2 23 34 2 44 56 我想要这样的输出 id points1 points2 points1 rank points2
  • pyCUDA无法打印结果

    最近 我使用 pip 为我的 python3 4 3 安装 pyCUDA 但我在测试示例代码时发现 https documen tician de pycuda tutorial html getting started https doc
  • 使用 Python 和 lmfit 拟合复杂模型?

    我想适合椭偏仪 http en wikipedia org wiki Ellipsometry使用 LMFit 将数据转换为复杂模型 两个测量参数 psi and delta 是复杂函数中的变量rho 我可以尝试将问题分离为实部和虚部共享参
  • 将整数系列转换为交替(双元)二进制系列

    我不知道如何最好地表达这个问题 因为在这里谷歌搜索和搜索总是让我找到更复杂的东西 我很确定这是基本的东西 但对于我的生活来说 我找不到一个好的方法来做到这一点下列 给定一个整数序列 比如说 for x in range 0 36 我想将这些
  • Python 内置对象的 __enter__() 和 __exit__() 在哪里定义?

    我读到每次使用 with 时都会调用该对象的 enter 和 exit 方法 我知道对于用户定义的对象 您可以自己定义这些方法 但我不明白这对于 打开 等内置对象 函数甚至测试用例是如何工作的 这段代码按预期工作 我假设它使用 exit 关
  • 如何找到多个 pandas 数据框中一对列与任意顺序对的交集?

    我有多个 pandas 数据框 为了简单起见 假设我有三个 gt gt df1 col1 col2 id1 A B id2 C D id3 B A id4 E F gt gt df2 col1 col2 id1 B A id2 D C id
  • 获取 Keras model.summary() 作为表

    我在 Keras 中创建了相当大的模型 我正在用 LaTeX 写一篇关于它的文章 为了很好地描述 LaTeX 中的 keras 模型 我想用它创建一个 LaTeX 表 我可以手动实现它 但我想知道是否有任何 更好 的方法来实现这一点 我四处
  • 我可以用关闭的文件对象做什么?

    当您打开文件时 它存储在一个打开的文件对象中 该对象使您可以访问该文件的各种方法 例如读取或写入 gt gt gt f open file0 gt gt gt f
  • Python:导入模块一次然后与多个文件共享

    我有如下文件 file1 py file2 py file3 py 假设这三个都使用 lib7 py lib8 py lib9 py 目前 这三个文件中的每一个都有以下行 import lib7 import lib8 import lib
  • 获取多个同名请求参数

    我的问题是给定的代码 from flask import Flask request app Flask name app route def hello return str request values get param None a
  • 如何从邻接表高效创建稀疏邻接矩阵?

    我正在与last fm http labrosa ee columbia edu millionsong lastfm数据集来自百万歌曲数据集 http labrosa ee columbia edu millionsong 数据以一组 j
  • 数据损坏 C++ 和 Python 之间的管道

    我正在编写一些代码 从 Python 获取二进制数据 将其通过管道传输到 C 对数据进行一些处理 在本例中计算互信息度量 然后将结果通过管道传输回 Python 在测试时 我发现如果我发送的数据是一组尺寸小于 1500 X 1500 的 2
  • 根据标点符号列表替换数据框中的标点符号[重复]

    这个问题在这里已经有答案了 使用 Canopy 和 Pandas 我有数据框 a 其定义如下 a pd read csv text txt df pd DataFrame a df columns test test txt 是一个单列文件
  • 将 Django 中的所有视图限制为经过身份验证的用户

    我是 Django 新手 我正在开发一个项目 该项目有一个登录页面作为其索引和一个注册页面 其余页面都必须仅限于登录用户 如果未经身份验证的用户尝试访问这些页面 则必须将他 她重定向到登录页面 我看到 login required装饰器会将
  • 从给定的项目列表创建子列表

    我首先要说的是以下问题不是为了家庭作业目的即使因为我几个月前就完成了软件工程师的工作 无论如何 今天我正在工作 一位朋友向我询问了这个奇怪的排序问题 我有一个包含 1000 行的列表 每行代表一个数字 我想创建 10 个子列表 每个子列表都
  • 用 pandas DataFrame 替换 mysql 数据库表中的行

    Python 版本 2 7 6 熊猫版本 0 17 1 MySQLdb 版本 1 2 5 在我的数据库中 PRODUCT 我有一张桌子 XML FEED 表 XML FEED 很大 数百万条记录 我有一个 pandas DataFrame
  • 为什么从 openAI 导入 Universe 模块时出现“无效语法”错误

    当我导入时universe来自 openAI 的模块 我收到以下错误 Traceback most recent call last File
  • PyObjC + Python 3.0 问题

    默认情况下 Cocoa Python 应用程序使用默认的 Python 运行时版本 2 5 如何配置我的 Xcode 项目以便它使用较新的 Python 3 0 运行时 我尝试用新版本替换项目中包含的Python framework 但它不
  • web3.py中sendTransaction和sendRawTransaction的区别

    这些发送交易的 web3 py 方法之间有什么实际区别 w3 eth sendTransaction w3 eth sendRawTransaction signed txn rawTransaction w3 eth sendTransa

随机推荐