Using pySerial for Serial Communication in Python
Serial interfaces remain a staple for embedded systems, serving as console channels or debug output paths in both bare-metal firmware and RTOS environments. Leveraging Python with pySerial enables rapid prototyping of tools that interact with serial devices.
Enumerating Available Ports
Identifying connected serial devices is the first step. The serial.tools.list_ports module provides access to system port information.
import serial
from serial.tools import list_ports
device_entries = list(list_ports.comports())
if not device_entries:
print("No serial devices detected.")
else:
print("Detected serial interfaces:")
for entry in device_entries:
print(f"{entry.device} — {entry.description}")
Typical output might resemble:
Detected serial interfaces:
COM4 — Standard Serial over Bluetooth link (COM4)
COM6 — Standard Serial over Bluetooth link (COM6)
COM5 — Standard Serial over Bluetooth link (COM5)
COM18 — Prolific PL2303GT USB Serial COM Port (COM18)
COM17 — Prolific USB-to-Serial Comm Port (COM17)
COM3 — Standard Serial over Bluetooth link (COM3)
Opening and Configuring a Port
A Serial instance can be constructed either by passing all settings at creation or by setting attributes beforehand. Supplying parameters during instantiation is concise for most use cases.
import serial
ser = serial.Serial('COM17', baudrate=115200) # Other parameters take library defaults
if ser.is_open:
print("Port opened successfully.")
print(f"Port name: {ser.name}")
else:
print("Failed to open port.")
Key consturctor arguments include:
- porrt — Identifier string or
None. - baudrate — Transmission speed; common values range from 50 to 4000000 bps.
- bytesize — Data bits:
FIVEBITS,SIXBITS,SEVENBITS,EIGHTBITS. - parity — Error checking:
PARITY_NONE,PARITY_EVEN,PARITY_ODD,PARITY_MARK,PARITY_SPACE. - stopbits — End-of-frame bits:
STOPBITS_ONE,STOPBITS_ONE_POINT_FIVE,STOPBITS_TWO. - xonxoff — Software flow control (
True/False). - rtscts — Hardware RTS/CTS flow control (
True/False). - dsrdtr — Hardware DSR/DTR flow control (
True/False). - timeout — Read timeout:
None(blocking),0(non-blocking), or seconds as float. - write_timeout — Write timeout with same semantics as
timeout.
Example with explicit framing:
import serial
ser = serial.Serial(
port='COM17',
baudrate=115200,
bytesize=serial.SEVENBITS,
parity=serial.PARITY_NONE,
stopbits=serial.STOPBITS_TWO,
timeout=0.5
)
Closing a Port
Releasing the interface requires invoking close().
import serial
ser = serial.Serial('COM17', 115200)
print("Port opened." if ser.is_open else "Port failed to open.")
ser.close()
print("Still open." if ser.is_open else "Port closed.")
Transmitting Bytes
The write() method sends raw bytes; textual data must be encoded. It returns the number of bytes transmitted and respects any configured write timeout.
import serial
ser = serial.Serial('COM17', 115200)
payload = "ABCDEFG".encode('utf-8')
sent_count = ser.write(payload)
print(f"Sent {sent_count} bytes via serial.")
ser.close()
Receiving Bytes
The read(size) method fetches up to size bytes, defaulting too one byte. Returned data is of type bytes. Timeout behavior follows the timeout parameter set at opening.
import serial
ser = serial.Serial('COM17', 115200, timeout=1)
while True:
chunk = ser.read(10)
if chunk:
print(chunk)
break # Exit after first non-empty read for demonstration
ser.close()