PySerial
PySerialDocs

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,
)
ParameterTypeDefaultDescription
portstr or NoneNoneDevice path (/dev/ttyUSB0, COM3)
baudrateint9600Communication speed in bits/second
bytesizeint8Data bits per byte (5, 6, 7, 8)
paritystr'N'Parity checking (N, E, O, M, S)
stopbitsfloat1Stop bits (1, 1.5, 2)
timeoutfloat or NoneNoneRead timeout in seconds. None = blocking, 0 = non-blocking
write_timeoutfloat or NoneNoneWrite timeout in seconds
xonxoffboolFalseSoftware (XON/XOFF) flow control
rtsctsboolFalseHardware (RTS/CTS) flow control
dsrdtrboolFalseDSR/DTR flow control
inter_byte_timeoutfloat or NoneNoneMax gap between bytes before returning
exclusivebool or NoneNoneExclusive 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 RateTypical Use
4800GPS modules (NMEA default)
9600Arduino default, low-speed sensors
19200Instrument control
38400Modbus RTU (common)
57600Faster sensor data
115200High-speed Arduino, ESP32
230400Bulk data transfer
460800High-speed logging
921600Maximum 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

ConstantValueUse
serial.FIVEBITS5Baudot code (rare)
serial.SIXBITS6Rare
serial.SEVENBITS7ASCII-only protocols
serial.EIGHTBITS8Standard (most devices)

Parity

ConstantCharDescription
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

ConstantValueUse
serial.STOPBITS_ONE1Standard
serial.STOPBITS_ONE_POINT_FIVE1.5Rare (some older hardware)
serial.STOPBITS_TWO2Noisy lines, Modbus RTU

Common Format Strings

FormatSettingsTypical Use
8N18 data, no parity, 1 stopArduino, most USB-serial devices
8E18 data, even parity, 1 stopModbus RTU
7E17 data, even parity, 1 stopSome industrial protocols
8N28 data, no parity, 2 stopNoisy 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

ValueBehavior
timeout=NoneBlock forever until requested bytes arrive
timeout=0Return immediately with whatever is in the buffer
timeout=1.5Wait 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 seconds

Inter-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 = True

DTR/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:

DeviceBaud RateFormatTimeoutNotes
Arduino Uno/Mega96008N12sDTR toggle resets board
ESP321152008N11s
GPS (NMEA)48008N11sinter_byte_timeout=0.1 helps
Modbus RTU96008E11sEven parity required
AT modem1152008N15srtscts=True recommended
RS-485 industrial96008N11sHalf-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)