Serial port access for Python, written in Rust. It has the API of pyserial 3.5, and adds an asyncio interface whose I/O calls return futures.
Runs on Windows, Linux and macOS with CPython 3.11 or newer, including the free-threaded build.
pip install oxiserialWheels are published for Windows, Linux and macOS. On other platforms pip builds from source, which needs a Rust toolchain.
Change the import; the rest of the code stays as it is.
import oxiserial as serial
with serial.Serial("COM3", 115200, timeout=1) as port:
port.write(b"*IDN?\n")
print(port.readline())Standard baud rates are available as an enum, and any other rate the driver supports is accepted as an int:
from oxiserial import Baudrate, Serial
port = Serial("/dev/ttyUSB0", Baudrate.B115200)
port.baudrate = 250000oxiserial.aio.Serial takes the same arguments. Its I/O methods return a
future that you can await:
import asyncio
from oxiserial.aio import Serial
async def main() -> None:
async with Serial("/dev/ttyUSB0", 115200, timeout=1) as port:
await port.write(b"*IDN?\n")
print(await port.readline())
asyncio.run(main())The same future can be waited on from plain threads, without an event loop:
from oxiserial.aio import Serial
port = Serial("COM3", 115200, timeout=1)
reply = port.readline()
port.write(b"*IDN?\n").wait()
print(reply.wait(timeout=2))
port.close()oxiserial.aio also has pyserial-asyncio's functions, so code written for
pyserial-asyncio changes only its import:
import asyncio
from oxiserial import aio as serial_asyncio
async def main() -> None:
reader, writer = await serial_asyncio.open_serial_connection(
url="COM3", baudrate=115200
)
writer.write(b"*IDN?\n")
await writer.drain()
print(await reader.readline())
writer.close()
await writer.wait_closed()
asyncio.run(main())create_serial_connection and connection_for_serial connect an asyncio
protocol to a port, as they do in pyserial-asyncio.
serial_for_url("loop://") opens a port that reads back what is written to
it. Other names open the device, as Serial does.
from oxiserial import serial_for_url
port = serial_for_url("loop://", baudrate=115200, timeout=0.01)
port.write(b"ping--")
print(port.read_until(expected=b"--")) # b'ping--'
port.close()oxiserial.aio.serial_for_url does the same and returns an
oxiserial.aio.Serial.
from oxiserial.tools.list_ports import comports
for port in sorted(comports()):
print(port.device, port.description, port.hwid)grep(regexp), from the same module, returns only the ports whose device,
description or hwid matches regexp, ignoring case.
write()also acceptsstrand sends it as UTF-8.- pyserial's deprecated camelCase methods (
inWaiting(),setRTS(), ...) are not provided; use the properties (in_waiting,rts, ...). serial_for_urlaccepts device names andloop://; other URLs, such assocket://, raiseValueError.Serial("loop://")also opens a loopback port.serial.rs485is not available yet;serial.threadedisoxiserial.threaded.
BSD-3-Clause, see LICENSE. Parts derived from pyserial carry its notice in LICENSES/pyserial.txt.