并发无关套接字API
项目描述
sockio
一个Python并发无关套接字库。
当处理通过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相比,以下功能不再可用:
- 独立控制套接字两端的能力(例如:关闭写入端)
- 虽然低级
socket.recv()
在达到EOF时返回空字符串,但TCP类会引发ConnectionEOFError
并关闭连接两端。 - 像
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_made
、connection_lost
和eof_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 的哈希值
算法 | 哈希摘要 | |
---|---|---|
SHA256 | 32eba7eaa0d402bb6fa27188ed7b0e476e49e4aba6276161c1773e37e7070353 |
|
MD5 | 41d0ddb60116bb697ef40b377ecae836 |
|
BLAKE2b-256 | 2177ffddcf26ec43832c576549c7d4ed933aedae0a851c50b39b159035e042ac |