pySerial

A cross-platform Python library that exposes a single, uniform class-based API for reading, writing, and configuring serial ports on Windows, macOS, Linux, and BSD.

Library
PyPI
v3.5
3,566stars
BSD 3-Clause License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
57/100Fair
Development Activity16
Maintenance20
Community92
Maturity60
Momentum40

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
74/100Good
Architecture78
Code Quality72
Innovation70
Learning Curve75

pySerial encapsulates serial port access behind one Serial class whose interface is identical no matter which operating system it runs on. It auto-selects a POSIX or Windows backend at import time, so code that opens a port, sets baud rate/parity/stop bits, and reads or writes bytes never has to branch on platform.

Beyond the core Serial class, the package bundles a URL-based connection scheme (serial_for_url()) that can address loopback ports, RFC 2217 remote serial bridges, or custom protocol handlers through a connection string instead of a raw device path, a serial.threaded module for event-driven reads via a Protocol/Transport pattern, cross-platform port enumeration through serial.tools.list_ports, and a built-in terminal program (pyserial-miniterm).

It has shipped as the de facto standard serial library for the Python ecosystem for over two decades, and is packaged directly by most major Linux distributions (Debian, Fedora, Arch, Gentoo) as well as conda-forge.

What You Get

  • A Serial class with the same constructor, properties (baudrate, bytesize, parity, stopbits, timeout, rtscts, xonxoff), and file-like read/write/readline methods across every supported platform.
  • serial_for_url() — open loopback (loop://), RFC 2217 remote (rfc2217://), hardware-grep (hwgrep://), or byte-spying (spy://) pseudo-ports through a connection string, extensible with custom protocol handlers.
  • serial.tools.list_ports for cross-platform enumeration of available serial devices, returning descriptions and hardware IDs, plus a pyserial-ports console entry point.
  • pyserial-miniterm, a built-in console terminal client for interacting with a serial device directly from the command line.
  • serial.threaded — a Protocol/Transport abstraction (connection_made/data_received/connection_lost) for running serial I/O on a background reader thread without hand-rolled polling loops.
  • An experimental RFC 2217 client implementation (serial.rfc2217) for accessing serial ports exposed over a network by a remote server.

Common Use Cases

  • Talking to embedded devices, microcontrollers, or industrial equipment connected via USB-to-serial or native RS-232.
  • Building a Python-based terminal or logging tool for hardware debugging using pyserial-miniterm or a custom serial.threaded.Protocol.
  • Enumerating and auto-detecting connected serial devices (e.g. Arduino boards, GPS receivers, modems) at application startup.
  • Bridging a physical serial port over a network with the RFC 2217 client/server so remote software can access hardware attached to a different machine.

Under The Hood

Architecture pySerial wraps platform-specific backends (serialposix.py, serialwin32.py) behind a common SerialBase defined in serialutil.py, with serial/__init__.py selecting the right implementation at import time via an os.name check. A URL-dispatch layer (serial_for_url()) provides a plugin-style mechanism where serial/urlhandler/protocol_*.py modules (loop, rfc2217, hwgrep, spy, cp2110, socket, alt) register handlers for different connection schemes, letting callers swap transports by changing a connection string rather than instantiation code. Additional layers sit on top of the core class: serial/threaded/ for event-driven reads via reader threads and Protocol/Packetizer/LineReader classes, serial/tools/ for port enumeration and the bundled terminal, and serial/rfc2217.py implementing the RFC 2217 telnet-based remote serial protocol. Because every backend and URL handler subclasses or wraps SerialBase, it is the module’s single point of contract enforcement.

Tech Stack The library is pure Python with no compiled extensions, targets Python 3.10+ per pyproject.toml, and builds via setuptools with a dynamically resolved version pulled from serial.__version__. An optional hidapi dependency enables CP2110 USB-HID-to-UART bridge support. Testing runs on pytest (configured in pyproject.toml, testpaths = ["test"]) with coverage.py branch coverage tracking, flake8 linting is configured via setup.cfg, and GitHub Actions (.github/workflows/test.yaml) runs CI on each change. Documentation is authored in reStructuredText and published through ReadTheDocs.

Code Quality The test/ directory holds roughly fifteen focused test modules (context managers, RS-485, RFC 2217, timeout handling, threaded reads, URL dispatch, and more) runnable via pytest or test/run_all_tests.py, and CI enforces they pass on every push. Error handling goes through a dedicated SerialException hierarchy (SerialException, SerialTimeoutException, PortNotOpenError) rather than raw OS errors, and newer modules like serialutil.py’s Timeout class and list_ports.py carry modern type annotations, though type-hint coverage is not uniform across the older platform backends. Naming is consistently snake_case, and every source file carries an SPDX license header.

API Design pySerial’s defining design choice is that the Serial class’s constructor signature and property-based configuration are identical on every supported platform, so application code needs zero conditional branching for OS differences. The URL-scheme mechanism extends that same class to loopback, RFC-2217-bridged, and byte-spying transports without changing call sites, and third-party protocol handlers can be registered by appending to protocol_handler_packages. serial.threaded mirrors an asyncio-style Protocol/Transport pattern for callback-driven reads instead of requiring hand-written polling loops, and the library ships both a port-enumeration API and a full terminal client (miniterm) in the same package — a combination few comparable serial libraries bundle together.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search