Configuration
Configure PySerial port settings including baud rate, data bits, parity, stop bits, flow control, timeouts, and buffer sizes.
All serial.Serial() constructor parameters and how to use them.
Constructor Parameters
import serial
ser = serial.Serial(
port='/dev/ttyUSB0',
baudrate=9600,
bytesize=serial.EIGHTBITS,
parity=serial.PARITY_NONE,
stopbits=serial.STOPBITS_ONE,
timeout=1,
xonxoff=False,
rtscts=False,
write_timeout=None,
dsrdtr=False,
inter_byte_timeout=None,
exclusive=None,
)| Parameter | Type | Default | Description |
|---|---|---|---|
port | str or None | None | Device path (/dev/ttyUSB0, COM3) |
baudrate | int | 9600 | Communication speed in bits/second |
bytesize | int | 8 | Data bits per byte (5, 6, 7, 8) |
parity | str | 'N' | Parity checking (N, E, O, M, S) |
stopbits | float | 1 | Stop bits (1, 1.5, 2) |
timeout | float or None | None | Read timeout in seconds. None = blocking, 0 = non-blocking |
write_timeout | float or None | None | Write timeout in seconds |
xonxoff | bool | False | Software (XON/XOFF) flow control |
rtscts | bool | False | Hardware (RTS/CTS) flow control |
dsrdtr | bool | False | DSR/DTR flow control |
inter_byte_timeout | float or None | None | Max gap between bytes before returning |
exclusive | bool or None | None | Exclusive port access (Linux only) |
Log serial data automatically
TofuPilot records test results from your PySerial scripts, tracks pass/fail rates, and generates compliance reports. Free to start.
Port Selection
Auto-detect a device by description or USB vendor/product ID:
import serial
import serial.tools.list_ports
def find_port(description=None, vid=None, pid=None):
"""Find a serial port by description substring or USB VID/PID."""
for port in serial.tools.list_ports.comports():
if description and description.lower() in port.description.lower():
return port.device
if vid and port.vid == vid and (pid is None or port.pid == pid):
return port.device
return None
# Find by name
arduino = find_port(description="Arduino")
# Find by USB IDs (FTDI chip)
ftdi = find_port(vid=0x0403, pid=0x6001)Baud Rate
Common Baud Rates
| Baud Rate | Typical Use |
|---|---|
| 4800 | GPS modules (NMEA default) |
| 9600 | Arduino default, low-speed sensors |
| 19200 | Instrument control |
| 38400 | Modbus RTU (common) |
| 57600 | Faster sensor data |
| 115200 | High-speed Arduino, ESP32 |
| 230400 | Bulk data transfer |
| 460800 | High-speed logging |
| 921600 | Maximum on most USB-serial adapters |
Transfer Time
Effective throughput for 8N1 (10 bits per byte: 1 start + 8 data + 1 stop):
def bytes_per_second(baudrate, data_bits=8, parity=False, stop_bits=1):
bits_per_byte = 1 + data_bits + (1 if parity else 0) + stop_bits
return baudrate / bits_per_byte
# 9600 baud, 8N1 = 960 bytes/sec
print(bytes_per_second(9600))
# 115200 baud, 8N1 = 11520 bytes/sec
print(bytes_per_second(115200))Data Format
Data Bits
| Constant | Value | Use |
|---|---|---|
serial.FIVEBITS | 5 | Baudot code (rare) |
serial.SIXBITS | 6 | Rare |
serial.SEVENBITS | 7 | ASCII-only protocols |
serial.EIGHTBITS | 8 | Standard (most devices) |
Parity
| Constant | Char | Description |
|---|---|---|
serial.PARITY_NONE | 'N' | No parity (most common) |
serial.PARITY_EVEN | 'E' | Even parity (Modbus RTU) |
serial.PARITY_ODD | 'O' | Odd parity |
serial.PARITY_MARK | 'M' | Always 1 |
serial.PARITY_SPACE | 'S' | Always 0 |
Stop Bits
| Constant | Value | Use |
|---|---|---|
serial.STOPBITS_ONE | 1 | Standard |
serial.STOPBITS_ONE_POINT_FIVE | 1.5 | Rare (some older hardware) |
serial.STOPBITS_TWO | 2 | Noisy lines, Modbus RTU |
Common Format Strings
| Format | Settings | Typical Use |
|---|---|---|
| 8N1 | 8 data, no parity, 1 stop | Arduino, most USB-serial devices |
| 8E1 | 8 data, even parity, 1 stop | Modbus RTU |
| 7E1 | 7 data, even parity, 1 stop | Some industrial protocols |
| 8N2 | 8 data, no parity, 2 stop | Noisy environments |
import serial
# 8N1 (default)
ser = serial.Serial('/dev/ttyUSB0', 9600)
# 8E1 for Modbus RTU
ser = serial.Serial('/dev/ttyUSB0', 9600,
parity=serial.PARITY_EVEN)
# 7E1 for legacy industrial
ser = serial.Serial('/dev/ttyUSB0', 9600,
bytesize=serial.SEVENBITS,
parity=serial.PARITY_EVEN)Timeout Configuration
Read Timeout Modes
| Value | Behavior |
|---|---|
timeout=None | Block forever until requested bytes arrive |
timeout=0 | Return immediately with whatever is in the buffer |
timeout=1.5 | Wait up to 1.5 seconds, then return what you have |
import serial
# Blocking read (waits forever)
ser = serial.Serial('/dev/ttyUSB0', 9600, timeout=None)
data = ser.read(10) # blocks until 10 bytes arrive
# Non-blocking read
ser.timeout = 0
data = ser.read(10) # returns immediately, 0-10 bytes
# Timed read
ser.timeout = 2
data = ser.read(10) # waits up to 2 secondsInter-byte Timeout
Useful for variable-length messages. Returns data when no new byte arrives within the inter-byte timeout, even if size bytes haven't been read yet.
import serial
ser = serial.Serial('/dev/ttyUSB0', 9600,
timeout=5,
inter_byte_timeout=0.05)
# Reads until 50ms gap between bytes or 5s total timeout
data = ser.read(1000)Write Timeout
import serial
ser = serial.Serial('/dev/ttyUSB0', 9600, write_timeout=2)
try:
ser.write(b'large payload...')
except serial.SerialTimeoutException:
print("Write timed out. Check flow control or receiver.")Flow Control
Software Flow Control (XON/XOFF)
import serial
ser = serial.Serial('/dev/ttyUSB0', 9600, xonxoff=True)XON (0x11, Ctrl+Q) resumes transmission. XOFF (0x13, Ctrl+S) pauses it. The driver handles this automatically when xonxoff=True. Don't use with binary data that might contain these bytes.
Hardware Flow Control (RTS/CTS)
import serial
ser = serial.Serial('/dev/ttyUSB0', 9600, rtscts=True)Requires RTS/CTS wires connected between devices. The transmitter checks CTS before sending. More reliable than XON/XOFF for high-speed or binary data.
DSR/DTR Flow Control
import serial
ser = serial.Serial('/dev/ttyUSB0', 9600, dsrdtr=True)
# Manual DTR control (e.g., reset Arduino)
ser.dtr = False
import time
time.sleep(0.1)
ser.dtr = TrueDTR/DSR is commonly used for modem handshaking. On Arduino boards, toggling DTR triggers a board reset.
Buffer Configuration
import serial
ser = serial.Serial('/dev/ttyUSB0', 9600, timeout=1)
# Set buffer sizes (platform-dependent, may not be supported)
try:
ser.set_buffer_size(rx_size=8192, tx_size=4096)
except AttributeError:
pass # not supported on this platform
# Check how much data is waiting
print(f"Input buffer: {ser.in_waiting} bytes")
# Clear buffers
ser.reset_input_buffer()
ser.reset_output_buffer()Exclusive Access
On Linux, you can lock a port so no other process can open it:
import serial
ser = serial.Serial('/dev/ttyUSB0', 9600, exclusive=True)This raises SerialException if another process already has the port open. Not supported on Windows or macOS.
Device Profiles
Common configurations for typical hardware:
| Device | Baud Rate | Format | Timeout | Notes |
|---|---|---|---|---|
| Arduino Uno/Mega | 9600 | 8N1 | 2s | DTR toggle resets board |
| ESP32 | 115200 | 8N1 | 1s | |
| GPS (NMEA) | 4800 | 8N1 | 1s | inter_byte_timeout=0.1 helps |
| Modbus RTU | 9600 | 8E1 | 1s | Even parity required |
| AT modem | 115200 | 8N1 | 5s | rtscts=True recommended |
| RS-485 industrial | 9600 | 8N1 | 1s | Half-duplex, needs direction control |
import serial
# Arduino
arduino = serial.Serial('/dev/ttyACM0', 9600, timeout=2)
# GPS module
gps = serial.Serial('/dev/ttyUSB0', 4800, timeout=1, inter_byte_timeout=0.1)
# Modbus RTU device
modbus = serial.Serial('/dev/ttyUSB1', 9600,
parity=serial.PARITY_EVEN, timeout=1)
# AT command modem
modem = serial.Serial('/dev/ttyUSB2', 115200,
timeout=5, rtscts=True)