PySerial
PySerialDocs

PySerial API Reference: Complete Documentation

Complete PySerial API documentation. All classes, methods, parameters, and exceptions with examples. Essential reference for serial programming.

Complete documentation for PySerial classes, methods, and utilities.

Serial Class

Main class for serial communication.

Constructor

serial.Serial(
    port=None,              # device name or None
    baudrate=9600,          # baud rate
    bytesize=EIGHTBITS,     # data bits
    parity=PARITY_NONE,     # parity
    stopbits=STOPBITS_ONE,  # stop bits  
    timeout=None,           # read timeout
    xonxoff=False,          # XON/XOFF flow control
    rtscts=False,           # RTS/CTS flow control
    write_timeout=None,     # write timeout
    dsrdtr=False,           # DSR/DTR flow control
    inter_byte_timeout=None, # inter-byte timeout
    exclusive=None          # exclusive access
)
ParameterTypeDescriptionDefault
portstr or NoneDevice name (/dev/ttyUSB0, COM3)None
baudrateintSpeed in bits per second9600
bytesizeintData bits (5, 6, 7, 8)8
paritystrParity (N, E, O, M, S)N
stopbitsfloatStop bits (1, 1.5, 2)1
timeoutfloat or NoneRead timeout in secondsNone
write_timeoutfloat or NoneWrite timeout in secondsNone
xonxoffboolSoftware flow controlFalse
rtsctsboolHardware (RTS/CTS) flow controlFalse
dsrdtrboolDSR/DTR flow controlFalse
inter_byte_timeoutfloat or NoneInter-byte timeoutNone
exclusivebool or NoneExclusive access (Linux only)None
# Basic connection
ser = serial.Serial('/dev/ttyUSB0', 9600)

# Full configuration
ser = serial.Serial(
    port='/dev/ttyUSB0',
    baudrate=115200,
    bytesize=8,
    parity='N',
    stopbits=1,
    timeout=1,
    write_timeout=1,
    rtscts=True
)

# Create without opening
ser = serial.Serial()
ser.port = '/dev/ttyUSB0'
ser.baudrate = 9600
ser.open()

Port naming:

  • Windows: COM1, COM3, \\.\COM10 (for COM10+)
  • Linux: /dev/ttyUSB0, /dev/ttyACM0, /dev/ttyS0
  • macOS: /dev/cu.usbserial-*, /dev/tty.usbserial-*

Feature availability:

  • exclusive: Linux only
  • set_buffer_size(): Platform dependent
  • out_waiting: Limited platform support

Properties

Port Information

port

str: Port name/path

name

str: Device name (same as port)

is_open

bool: True if port is open

print(f"Port: {ser.port}")
print(f"Name: {ser.name}")
print(f"Open: {ser.is_open}")

Communication Settings

# Current settings (read/write)
ser.baudrate = 115200       # int: baud rate
ser.bytesize = 8            # int: data bits (5-8)
ser.parity = 'N'            # str: parity setting
ser.stopbits = 1            # float: stop bits
ser.timeout = 2.0           # float: read timeout
ser.write_timeout = 1.0     # float: write timeout
ser.inter_byte_timeout = 0.1 # float: inter-byte timeout

# Example: Change baud rate
old_baud = ser.baudrate
ser.baudrate = 57600
print(f"Baud rate changed from {old_baud} to {ser.baudrate}")

Flow Control

# Flow control settings (read/write)
ser.xonxoff = True          # bool: software flow control
ser.rtscts = False          # bool: RTS/CTS flow control  
ser.dsrdtr = False          # bool: DSR/DTR flow control

# Example: Enable hardware flow control
ser.rtscts = True
print(f"RTS/CTS flow control: {ser.rtscts}")

Buffer Status

# Buffer information (read-only)
waiting_bytes = ser.in_waiting    # int: bytes in input buffer
out_bytes = ser.out_waiting       # int: bytes in output buffer (if supported)

print(f"Input buffer: {waiting_bytes} bytes")
if hasattr(ser, 'out_waiting'):
    print(f"Output buffer: {out_bytes} bytes")

Modem Control Lines

# Modem status lines (read-only)
print(f"CTS (Clear To Send): {ser.cts}")
print(f"DSR (Data Set Ready): {ser.dsr}")
print(f"RI (Ring Indicator): {ser.ri}")
print(f"CD (Carrier Detect): {ser.cd}")

# Modem control lines (read/write)
ser.dtr = True              # bool: Data Terminal Ready
ser.rts = False             # bool: Request To Send

print(f"DTR: {ser.dtr}")
print(f"RTS: {ser.rts}")

Read Methods

read(size=1)

Read up to size bytes from the serial port.

def read(size=1):
    """Read up to size bytes"""
    pass

Parameters:

  • size (int): Maximum number of bytes to read

Returns: bytes object (may be shorter than requested)

Examples:

# Read 10 bytes
data = ser.read(10)
print(f"Read {len(data)} bytes: {data}")

# Read single byte
byte = ser.read(1)
if byte:
    print(f"Byte value: {byte[0]:02X}")

# Read with timeout handling
ser.timeout = 2
data = ser.read(100)
if len(data) < 100:
    print(f"Timeout: only got {len(data)} bytes")

readline(size=-1)

Read until line terminator or size limit.

def readline(size=-1):
    """Read until \\n or size limit"""
    pass

Parameters:

  • size (int): Maximum bytes to read (-1 for unlimited)

Returns: bytes object including line terminator

Examples:

# Read complete line
line = ser.readline()
text = line.decode('utf-8').strip()

# Read with size limit
line = ser.readline(100)  # Max 100 bytes

# Handle different line endings
line = ser.readline()
if line.endswith(b'\r\n'):
    text = line[:-2].decode('utf-8')
elif line.endswith(b'\n'):
    text = line[:-1].decode('utf-8')

read_until(expected=b'\n', size=None)

Read until specific bytes found.

def read_until(expected=b'\\n', size=None):
    """Read until expected bytes found"""
    pass

Parameters:

  • expected (bytes): Bytes to search for
  • size (int or None): Maximum bytes to read

Returns: bytes object including expected bytes

Examples:

# Read until "OK"
response = ser.read_until(b'OK')

# Read until custom delimiter  
data = ser.read_until(b'</packet>')

# With size limit
data = ser.read_until(b'END', size=1000)

# Binary packet reading
packet = ser.read_until(b'\xAA\x55')  # Read until header

read_all()

Read all available bytes.

def read_all():
    """Read all available data"""
    pass

Returns: bytes object with all buffered data

Examples:

# Read everything in buffer
data = ser.read_all()
print(f"Got {len(data)} bytes")

# Wait for data, then read all
time.sleep(1)  # Let data accumulate
if ser.in_waiting:
    data = ser.read_all()

Write Methods

write(data)

Write bytes to the serial port.

def write(data):
    """Write bytes to port"""
    pass

Parameters:

  • data (bytes or bytearray): Data to write

Returns: int number of bytes written

Examples:

# Write bytes
bytes_written = ser.write(b'Hello')
print(f"Wrote {bytes_written} bytes")

# Write string (must encode first)
message = "Temperature: 25.6C"
bytes_written = ser.write(message.encode('utf-8'))

# Write with line ending
ser.write(b'AT+GMR\r\n')

# Write binary data
import struct
data = struct.pack('>HHf', 1234, 5678, 25.6)
ser.write(data)

writelines(lines)

Write list of byte strings.

def writelines(lines):
    """Write sequence of bytes"""
    pass

Parameters:

  • lines (iterable): Sequence of bytes objects

Returns: None

Examples:

# Write multiple commands
commands = [
    b'AT\r\n',
    b'ATE0\r\n', 
    b'AT+GMR\r\n'
]
ser.writelines(commands)

# Equivalent to:
for cmd in commands:
    ser.write(cmd)

flush()

Force transmission of buffered data.

def flush():
    """Force write buffer flush"""
    pass

Examples:

# Send data immediately
ser.write(b'URGENT_COMMAND\r\n')
ser.flush()  # Don't wait for buffer

# Read immediate response
response = ser.readline()

Control Methods

open()

Open the serial port.

def open():
    """Open serial port"""
    pass

Raises: SerialException if port cannot be opened

Examples:

# Create and open manually
ser = serial.Serial()
ser.port = '/dev/ttyUSB0'
ser.baudrate = 9600

try:
    ser.open()
    print("✅ Port opened")
except serial.SerialException as e:
    print(f"❌ Failed to open: {e}")

close()

Close the serial port.

def close():
    """Close serial port"""
    pass

Examples:

# Always close in finally block
try:
    ser = serial.Serial('/dev/ttyUSB0', 9600)
    # Use serial port
finally:
    if ser.is_open:
        ser.close()
        print("Port closed")

reset_input_buffer()

Clear input buffer.

def reset_input_buffer():
    """Clear input buffer"""
    pass

Examples:

# Clear stale data before sending command
ser.reset_input_buffer()
ser.write(b'AT+GMR\r\n')
response = ser.readline()

reset_output_buffer()

Clear output buffer.

def reset_output_buffer():
    """Clear output buffer"""
    pass

send_break(duration=0.25)

Send break condition.

def send_break(duration=0.25):
    """Send break signal"""
    pass

Parameters:

  • duration (float): Break duration in seconds

Examples:

# Send standard break
ser.send_break()

# Send long break for attention
ser.send_break(1.0)

# Break sequence for modem
ser.send_break(0.5)
time.sleep(0.1)
ser.write(b'+++')

set_buffer_size(rx_size=4096, tx_size=None)

Set buffer sizes (platform dependent).

def set_buffer_size(rx_size=4096, tx_size=None):
    """Set buffer sizes"""
    pass

Parameters:

  • rx_size (int): Receive buffer size
  • tx_size (int or None): Transmit buffer size

Examples:

# Set larger buffers for high-speed
try:
    ser.set_buffer_size(rx_size=8192, tx_size=4096)
    print("✅ Buffer sizes set")
except AttributeError:
    print("⚠️  Platform doesn't support buffer size control")

Port Discovery

list_ports.comports()

List all available serial ports.

def comports(include_links=False):
    """List available serial ports"""
    pass

Parameters:

  • include_links (bool): Include symbolic links (Linux/macOS)

Returns: List of ListPortInfo objects

Examples:

import serial.tools.list_ports

# Basic port listing
ports = serial.tools.list_ports.comports()
for port in ports:
    print(f"{port.device}: {port.description}")

# Detailed information
for port in ports:
    print(f"Device: {port.device}")
    print(f"Description: {port.description}")
    print(f"Hardware ID: {port.hwid}")
    if hasattr(port, 'vid') and port.vid:
        print(f"VID:PID: {port.vid:04X}:{port.pid:04X}")
    print()

ListPortInfo Properties

# Port information object properties
port.device         # str: device name ('/dev/ttyUSB0', 'COM3')
port.name           # str: short device name
port.description    # str: human readable description  
port.hwid          # str: hardware ID string

# USB device information (if available)
port.vid           # int: vendor ID
port.pid           # int: product ID
port.serial_number # str: serial number
port.location      # str: physical location
port.manufacturer  # str: manufacturer name
port.product       # str: product name
port.interface     # str: interface description

# Platform-specific properties
port.subsystem     # str: subsystem (Linux)
port.usb_info()    # method: detailed USB info

Port Filtering

def find_ports_by_description(description_filter):
    """Find ports by description"""
    matching_ports = []
    
    for port in serial.tools.list_ports.comports():
        if description_filter.lower() in port.description.lower():
            matching_ports.append(port.device)
    
    return matching_ports

# Find specific devices
arduino_ports = find_ports_by_description("Arduino")
ftdi_ports = find_ports_by_description("FTDI")
prolific_ports = find_ports_by_description("Prolific")

print(f"Arduino ports: {arduino_ports}")
def find_ports_by_vid_pid(vid, pid=None):
    """Find ports by Vendor ID and optional Product ID"""
    matching_ports = []
    
    for port in serial.tools.list_ports.comports():
        if hasattr(port, 'vid') and port.vid == vid:
            if pid is None or port.pid == pid:
                matching_ports.append(port.device)
    
    return matching_ports

# Common vendor IDs
FTDI_VID = 0x0403
PROLIFIC_VID = 0x067B
CH340_VID = 0x1A86

ftdi_ports = find_ports_by_vid_pid(FTDI_VID)
print(f"FTDI devices: {ftdi_ports}")
def categorize_ports():
    """Categorize ports by type"""
    categories = {
        'usb_serial': [],
        'built_in': [],
        'bluetooth': [],
        'other': []
    }
    
    for port in serial.tools.list_ports.comports():
        desc_lower = port.description.lower()
        
        if 'usb' in desc_lower or hasattr(port, 'vid'):
            categories['usb_serial'].append(port.device)
        elif 'bluetooth' in desc_lower:
            categories['bluetooth'].append(port.device)
        elif port.device in ['COM1', 'COM2', '/dev/ttyS0', '/dev/ttyS1']:
            categories['built_in'].append(port.device)
        else:
            categories['other'].append(port.device)
    
    return categories

# Usage
ports_by_type = categorize_ports()
for category, ports in ports_by_type.items():
    if ports:
        print(f"{category}: {ports}")

Constants

Data Format Constants

# Byte sizes
serial.FIVEBITS = 5
serial.SIXBITS = 6  
serial.SEVENBITS = 7
serial.EIGHTBITS = 8

# Parity
serial.PARITY_NONE = 'N'
serial.PARITY_EVEN = 'E'
serial.PARITY_ODD = 'O'
serial.PARITY_MARK = 'M'
serial.PARITY_SPACE = 'S'

# Stop bits
serial.STOPBITS_ONE = 1
serial.STOPBITS_ONE_POINT_FIVE = 1.5
serial.STOPBITS_TWO = 2

Usage Examples

# Using constants for clarity
ser = serial.Serial(
    port='/dev/ttyUSB0',
    baudrate=9600,
    bytesize=serial.EIGHTBITS,
    parity=serial.PARITY_EVEN,
    stopbits=serial.STOPBITS_ONE
)

# Or use values directly
ser = serial.Serial(
    port='/dev/ttyUSB0',
    baudrate=9600,
    bytesize=8,
    parity='E',
    stopbits=1
)

Exceptions

SerialException

Base exception for all serial errors.

try:
    ser = serial.Serial('/dev/nonexistent')
except serial.SerialException as e:
    print(f"Serial error: {e}")

Common causes:

  • Port doesn't exist
  • Permission denied
  • Device disconnected
  • Invalid parameters

SerialTimeoutException

Raised on timeout operations (subclass of SerialException).

try:
    ser.timeout = 1
    data = ser.read(100)  # May timeout
except serial.SerialTimeoutException:
    print("Read operation timed out")

Exception Hierarchy

Exception
 └── SerialException
      ├── SerialTimeoutException
      ├── PortNotOpenError  
      └── WriteTimeoutError

Comprehensive Error Handling

def safe_serial_operation(port, operation):
    """Perform serial operation with complete error handling"""
    
    try:
        ser = serial.Serial(port, 9600, timeout=1)
        result = operation(ser)
        return result
        
    except serial.SerialTimeoutException:
        print("⏱️  Operation timed out")
    except serial.SerialException as e:
        print(f"📡 Serial error: {e}")
    except PermissionError:
        print("🔒 Permission denied")
    except FileNotFoundError:
        print("📁 Port not found")
    except Exception as e:
        print(f"❌ Unexpected error: {e}")
    finally:
        if 'ser' in locals() and ser.is_open:
            ser.close()
    
    return None

# Usage
def my_operation(ser):
    ser.write(b'test')
    return ser.read(10)

result = safe_serial_operation('/dev/ttyUSB0', my_operation)

Context Manager Support

PySerial supports Python's with statement for automatic resource management.

# Automatic port closing
with serial.Serial('/dev/ttyUSB0', 9600, timeout=1) as ser:
    ser.write(b'data')
    response = ser.read(100)
    # Port automatically closed when exiting 'with' block

# Equivalent to:
ser = serial.Serial('/dev/ttyUSB0', 9600, timeout=1)
try:
    ser.write(b'data')
    response = ser.read(100)
finally:
    ser.close()

URL Handlers

PySerial supports URL-style port specifications:

socket://

TCP/IP socket connection

rfc2217://

Remote serial port over network

loop://

Loopback connection for testing

hwgrep://

Hardware-based port selection

URL Examples

# TCP socket
ser = serial.Serial('socket://192.168.1.100:7777', timeout=1)

# RFC2217 remote serial
ser = serial.Serial('rfc2217://server.example.com:4000', baudrate=9600)

# Loopback for testing
ser = serial.Serial('loop://', timeout=1)

# Hardware grep
ser = serial.Serial('hwgrep://0403:6001')  # Find FTDI device
ser = serial.Serial('hwgrep://.*Arduino.*')  # Find Arduino by description

Version Information

import serial

# PySerial version
print(f"PySerial version: {serial.__version__}")

# Check for specific features
if hasattr(serial, 'VERSION'):
    print(f"Version tuple: {serial.VERSION}")

# Platform-specific version info
try:
    import serial.win32
    print("Windows serial support available")
except ImportError:
    pass

try:
    import serial.posix
    print("POSIX serial support available")  
except ImportError:
    pass

Complete API Coverage: This reference covers all PySerial classes, methods, properties, and exceptions. Use it as your definitive guide for PySerial programming.

Next Steps

This API reference provides complete documentation for PySerial. For specific use cases and implementation patterns, see the examples and configuration guides.

How is this guide?