Python
COM Ports
Serial Communication
Programming
Tutorials

Listing available com ports with Python

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

Introduction

Listing available serial ports is the first practical step in almost any Python program that talks to hardware. Even though the title says COM ports, the same task applies across Windows, macOS, and Linux, with different device names on each platform. In Python, the standard solution is to use pyserial, which provides a cross-platform port discovery API.

Install the Right Library

The usual package is pyserial. It includes the serial communication classes and the list_ports helpers.

bash
python -m pip install pyserial

Once installed, use serial.tools.list_ports rather than trying to guess device names manually.

Basic Port Listing

Here is the simplest useful example:

python
1from serial.tools import list_ports
2
3ports = list_ports.comports()
4
5for port in ports:
6    print(port.device)

Typical output might look like:

  • Windows: COM3
  • macOS: /dev/cu.usbserial-1410
  • Linux: /dev/ttyUSB0

This is already more reliable than hardcoding one port name and hoping the device always appears in the same place.

Get More Than Just the Device Name

Each result object contains helpful metadata such as description and hardware id.

python
1from serial.tools import list_ports
2
3for port in list_ports.comports():
4    print("device:", port.device)
5    print("description:", port.description)
6    print("hwid:", port.hwid)
7    print("---")

This is useful when multiple devices are connected and you need to identify the correct one programmatically.

For example, a USB serial adapter may expose a recognizable vendor and product identifier in hwid.

Filter Ports by Description or Hardware ID

If your application works with one known type of device, filter the discovered ports instead of asking the user to guess.

python
1from serial.tools import list_ports
2
3matches = []
4for port in list_ports.comports():
5    text = f"{port.description} {port.hwid}".lower()
6    if "arduino" in text or "vid:pid=2341" in text:
7        matches.append(port.device)
8
9print(matches)

This is not perfect for every device, but it is a strong starting point for hardware-specific tools.

Sort and Present Ports Predictably

On some systems, the returned order may not be the order you want to display. Sorting makes the output stable and easier to read.

python
1from serial.tools import list_ports
2
3ports = sorted(list_ports.comports(), key=lambda p: p.device)
4for port in ports:
5    print(f"{port.device}: {port.description}")

Stable presentation matters when you are building a CLI or a GUI that asks the user to choose one port.

Test the Port by Opening It

Listing a port only tells you that the operating system currently exposes it. It does not prove the port is usable or that your application has permission to open it.

python
1import serial
2from serial.tools import list_ports
3
4for info in list_ports.comports():
5    try:
6        with serial.Serial(info.device, baudrate=9600, timeout=1) as ser:
7            print(f"opened {info.device} successfully")
8    except serial.SerialException as exc:
9        print(f"could not open {info.device}: {exc}")

Use this carefully, because opening a port can affect devices that are already in use by another application.

Platform Notes

Even though the API is cross-platform, the names differ:

  • Windows uses names like COM3
  • Linux often uses /dev/ttyS0, /dev/ttyUSB0, or /dev/ttyACM0
  • macOS commonly exposes /dev/tty.* and /dev/cu.*

On macOS, cu devices are often the better choice for initiating outgoing serial connections, while tty devices have historical call-in behavior.

Common Pitfalls

  • Hardcoding one port name instead of discovering ports dynamically.
  • Assuming a listed port can always be opened successfully.
  • Ignoring metadata like description and hwid when several devices are present.
  • Treating COM naming as Windows-only and forgetting that the same discovery problem exists on Unix-like systems.
  • Opening ports aggressively during discovery and accidentally interfering with another process.

Summary

  • Use pyserial and serial.tools.list_ports.comports() to list available serial ports.
  • The API works across Windows, macOS, and Linux, even though device names differ.
  • Metadata such as description and hwid helps identify the correct device.
  • Listing a port is different from proving that it can be opened and used.
  • Dynamic discovery is much safer than hardcoding one port name in serial tools.

Related reading
Free course
Beginner
7 lessons
2 hours
Tackling System Design Interview Problems

A short course that equips you with the skills to approach system design interviews methodically.

Start the free course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

All Rights Reserved.