How to establish a serial communication channel in Python

Consider this scenario that we have to build a monitoring system for a solar power plant. To ensure optimal performance, we need to monitor critical data such as power generation and environmental conditions. The data is being generated by various sensors and control devices deployed throughout the facility. However, we need to find a way to communicate with those sensors using the Python-based control software. Fortunately, pySerial can help us overcome this challenge by establishing UART serial communication channels to communicate with our control devices.

A Python based software communicating with the control devices of each solar panel cluster
A Python based software communicating with the control devices of each solar panel cluster

In this Answer, we’ll explore the key features and functionalities of pySerial, starting with the basics of finding available system ports. We’ll then delve into the process of initiating a serial port connection, configuring essential parameters like baud rate and data bits, and finally, communicating seamlessly over the channel. Additionally, we’ll uncover other useful controls and attributes that pySerial offers, providing you with a comprehensive guide to mastering serial communication with Python.

Note: If you want to learn more about UART serial communication protocol, see this Answer on our platform.

The pySerial

The pySerial is a Python library that allows us to establish serial communication channels on Windows, Linux, and OSX. It supports various baud rates, and its APIs make serial channel communication intuitive.

Get available system ports

The first and foremost requirement to establish a serial communication channel is a physical port on the system. Initially, serial communication required DB9 connectors, but that is not a restriction now. Serial communication channels can also be established using Ethernet or USB connections. No matter the connection type, there is always a port number associated with it. To find all the available connections that can establish serial communication channels, we can use the tools.list_ports module provided by pySerial.

import serial
import serial.tools.list_ports as ports
p_list = ports.comports()
for i in p_list:
print(i.name)

  • Line 4: Fetch the list of objects containing individual port information.

  • Line 6–7: Loop over the list of objects and print the name attribute from each object.

Initiate a serial port connection

We need to supply the communication port number, baud rate, and data packet parameters to initialize a serial communication channel. The pySerial has default values for the baud rate and the data packet composition parameters, and we can instantiate a serial port by only supplying the port name as a string..

import serial
s = serial.Serial('Port name')

With this basic setup, all other values are set to default. These values can easily be modified using simple API commands.

  • Baud rate: The default value of the baud rate set by pySerial is 9600 and can be modified by changing the baudrate object’s attribute. The pySerial supports a long list of baud rates up to 4×1064\times10^6bits per second. The code below prints a list of supported baud rates using the BAUDRATES attribute of the Serial object.

import serial
import serial.tools.list_ports as ports
p_list = ports.comports()
for i in p_list:
print(i.name)

  • Data bits: The default value of the data bits set by pySerial is EIGHTBIS (8 bits) and can be modified by changing the bytesize attribute of the serial.Serial object. Supported data bits numbers in pySerial are FIVEBITS, SIXBITS, SEVENBITS, and EIGHTBITS.

s.bytesize = SIXBITS

  • Parity bit: The default value of the parity bit set by the pySerial is PARITY_NONE and can be modified by changing the parity attribute of the serial.Serial object. The values of PARITY attribute supported by pySerial are PARITY_NONE, PARITY_EVEN, PARITY_ODD, PARITY_MARK, and PARITY_SPACE.

s.parity = PARITY_NONE

  • Stop bits: The default number of parity bits set by pySerial is STOPBITS_ONE and can be modified by changing the stopbits attribute of the serial.Serial object. The pySerial supports a long list of baud rates up to 4×1064\times10^6bits per second. The values of stopbits attribute supported by pySerial are STOPBITS_ONE, STOPBITS_ONE_POINT_FIVE, and STOPBITS_TWO.

s.stopbits = STOPBITS_ONE

Note: We don’t need to change the number of start bits as there is always a single start bit. No other options are available.

Communicating over the channel

A serial communication channel has two communication attributes: read (to get data) and write (to send data).

Read

The read() function is used to receive data from the channel
The read() function is used to receive data from the channel

The read() function in pySerial takes the number of bytes (or data packets) to be read from the port in integer format. When a data packet is received and processed by a system, all the bits other than the data bits are discarded, and all we get are the bytes of data as the output of the read() function. The number of bits in every byte will be determined by the bytesize attribute of the pySerial object.

num_bytes = 10
data = s.read(num_bytes)

Write

The write() function is used to transmit data to the channel
The write() function is used to transmit data to the channel

The write() function in pySerial takes the data to send as its input. It also returns the number of bytes sent through the channel.

data = 47
s.write(data)

Buffer control

The buffer control system
The buffer control system

Data is continuously being pumped in whether we read it or not, and is temporarily stored in a FIFO buffer until we access it using the read() function. Similarly, if the channel is receiving data faster than it can transmit it, it’ll be temporarily stored in a FIFO buffer as well. The pySerial provides us the following commands to manage these buffers according to our needs:

  • in_waiting: The number of bytes available in the input buffer.

  • out_waiting: Contains the number of bytes available in the output buffer.

  • reset_input_buffer(): This function flushes all the data in the input buffer. This option can prove useful to remove any lag in communication at the expense of some data.

  • reset_output_buffer(): This function flushes all the data in the output buffer. This option can prove useful to remove any lag in communication at the expense of some data.

  • set_buffer_size(): This function takes the buffer size as input and can be used to change the size of the input buffer. The default buffer size pySerial sets is 4096 KB but can be set to any value below 2312^{31} bytes. The option is especially useful when the baud rate is high and there are chances of packets dropping.

Conclusion

Serial communication is crucial in various technological applications. The pySerial is a powerful tool for seamless communication across multiple platforms. It allows us to identify system ports, initiate serial port connections, fine-tune parameters, and enable smooth data transfer. The pySerial simplifies the complexities of serial communication, making it a valuable tool for connecting Python applications to external devices.

Free Resources

Copyright ©2025 Educative, Inc. All rights reserved