跳转到主要内容

并发无关套接字API

项目描述

sockio

Pypi version

一个Python并发无关套接字库。

spec in action

当处理通过TCP工作并在简单的REQ-REP通信协议(例如:SCPI)中工作的仪器时很有用。

迄今为止已实现REQ-REP和流语义,并带有自动重连功能。

基于asyncio编写的基实现,支持不同的并发模型

  • asyncio
  • 经典阻塞API
  • 基于future的API
  • Python 2兼容的阻塞API(对于那些被困在Python 2中的可怜灵魂)

安装

在你的Python环境中

pip install sockio

使用

asyncio

import asyncio
from sockio.aio import TCP

async def main():
    sock = TCP('acme.example.com', 5000)
    # Assuming a SCPI complient on the other end we can ask for:
    reply = await sock.write_readline(b'*IDN?\n')
    print(reply)

asyncio.run(main())

经典

from sockio.sio import TCP

sock = TCP('acme.example.com', 5000)
reply = sock.write_readline(b'*IDN?\n')
print(reply)

concurrent.futures

from sockio.sio import TCP

sock = TCP('acme.example.com', 5000, resolve_futures=False)
reply = sock.write_readline(b'*IDN?\n').result()
print(reply)

Python 2兼容性

from sockio.py2 import TCP

sock = TCP('acme.example.com', 5000)
reply = sock.write_readline(b'*IDN?\n').result()
print(reply)

功能

sockio TCP对象的主要目标是便于与监听TCP套接字的仪器进行通信。

最常见的案例包括预期与ASCII协议(如SCPI)的REQ/REP语义的仪器。在这些情况下,大多数命令都转化为主机和仪器之间交换的小数据包。在这个库中,已经注意到了尽可能减少延迟。这转化为创建TCP对象时的以下默认设置

  • TCP无延迟功能已激活。可以通过TCP(..., no_delay=False)禁用。这可以阻止内核应用Nagle算法
  • TCP ToS设置为LOWDELAY。这实际上优先处理我们的数据包,以有利于其他并发通信。可以通过TCP(tos=IPTOS_NORMAL)禁用

代价

在详细说明功能之前,请注意,这种抽象是有代价的。有意地,与低级socket API相比,以下功能不再可用:

  1. 独立控制套接字两端的能力(例如:关闭写入端)
  2. 虽然低级socket.recv()在达到EOF时返回空字符串,但TCP类会引发ConnectionEOFError并关闭连接两端。
  3. os.dup()这样的巧妙低级操作,使套接字变为非阻塞

请求-响应语义

许多仪器都有请求-回复协议。sockio TCP提供了write_read方法族,这些方法简化了与这些仪器的通信。这些方法是原子的,这意味着不同的任务或线程可以安全地使用相同的套接字对象(尽管我会质疑自己在库/应用程序中为什么要这样做)。

自动重连

sock = TCP('acme.example.com', 5000)
reply = await sock.write_readline(b'*IDN?\n')
print(reply)

# ... kill the server connection somehow and bring it back to life again

# You can use the same socket object. It will reconnect automatically
# and work "transparently"
reply = await sock.write_readline(b'*IDN?\n')
print(reply)

自动重连功能在例如,你将设备从一个地方移动到另一个地方,或者你需要在夜间关闭设备(地球感谢你节约能源!)时非常有用。

超时

TCP构造函数提供了一个connection_timeout,用于打开连接时,以及一个在执行任何数据I/O操作(读取、写入、read_writeline等)时考虑的timeout参数。默认情况下,它们都是None,表示无限超时。

sock = TCP('acme.example.com', 5000, connection_timeout=0.1, timeout=1)

此外,您可以在调用每个数据I/O方法时通过提供替代超时参数来覆盖对象超时

sock = TCP('acme.example.com', 5000, timeout=1)
# the next call will raise asyncio.TimeoutError if it takes more than 0.1s
reply = await sock.write_readline(b'*IDN?\n', timeout=0.1)
print(reply)

自定义EOL

在基于行的协议中,有时人们认为\n不是一个好的EOL字符。sockio TCP可以使用不同的EOL字符进行自定义。示例

sock = TCP('acme.example.com', 5000, eol=b'\r')

可以在任何readline方法中覆盖EOL字符。示例

await sock.write_readline(b'*IDN?\n', eol=b'\r')

连接事件回调

您可以通过在sockio TCP构造函数上注册回调来通知connection_madeconnection_losteof_received事件

这在例如,您希望每次套接字重新连接时执行特定过程以确保您的配置正确时非常有用。示例

async def connected():
    await sock.write(b'ACQU:TRIGGER HARDWARE\n')
    await sock.write(b'DISPLAY OFF\n')

sock = TCP('acme.example.com', 5000, on_connection_made=connected)

(请参阅examples/req-rep/client.py)

连接事件回调在python 2兼容模块中不可用。

sockio TCP是异步可迭代对象。这意味着行流与以下内容一样简单

sock = TCP('acme.example.com', 5000, eol=b'\r')

async for line in sock:
    print(line)

流在python 2兼容模块中不可用。如果您需要它们,请通过编写问题通知我。也请自由地提交PR!

缺少的功能

  • 连接重试
  • trio事件循环
  • curio事件循环

通过提交PR带来您自己的并发库,加入我们的行列!

我特别希望看到基于trio和curio的实现。

项目详情


下载文件

下载适用于您平台的文件。如果您不确定选择哪个,请了解更多关于安装包的信息。

源代码分发

sockio-0.15.0.tar.gz (25.4 kB 查看哈希值)

上传时间 源代码

由以下支持