Listing available com ports with Python

我正在寻找一个简单的方法来列出所有可用的电脑上的康普特。

我已经找到了这个方法,但它是 Windows 特有的: 在 Windows 上列出串行(COM)端口? ?

我在 Windows7电脑上使用 Python3和 pySerial。

我在 pySerial API (http://pyserial.sourceforge.net/pyserial_api.html)中发现了一个函数 serial.tools.list_ports.comports(),它列出了 com 端口(正是我想要的)。

import serial.tools.list_ports
print(list(serial.tools.list_ports.comports()))

但似乎不起作用。当我的 USB 到 COM 网关连接到 PC 时(我在设备管理器中看到 COM5) ,这个 COM 端口不包括在 list_ports.comports()返回的列表中。相反,我只得到 COM4,似乎连接到一个调制解调器(我没有看到它在 COM & LPT 设备管理器部分) !

你知道为什么它不工作吗? 你有没有其他的解决方案,不是系统特定的?

273800 次浏览

Several options are available:

使用 NULL lpDeviceName 调用 QueryDosDevice以列出所有 DOS 设备。然后依次使用 CreateFile 和 GetCommConfig以及每个设备的名称来判断它是否是一个串行端口。

使用 GUID _ devINTERFACE _ COMPORT 的 ClassGuid 调用 SetupDiGetClassDevs

WMI 也可用于 C/C + + 程序

Win32新闻组和 CodeProject 上有一些对话,呃,项目

这是我用的密码。

在 Windows 8.1 x64,Windows 10 x64,Mac OS X 10.9.x/10.10.x/10.11.x 和 Ubuntu 14.04.14.10.15.04.15.10上成功测试了 Python 2和 Python 3。

import sys
import glob
import serial




def serial_ports():
""" Lists serial port names


:raises EnvironmentError:
On unsupported or unknown platforms
:returns:
A list of the serial ports available on the system
"""
if sys.platform.startswith('win'):
ports = ['COM%s' % (i + 1) for i in range(256)]
elif sys.platform.startswith('linux') or sys.platform.startswith('cygwin'):
# this excludes your current terminal "/dev/tty"
ports = glob.glob('/dev/tty[A-Za-z]*')
elif sys.platform.startswith('darwin'):
ports = glob.glob('/dev/tty.*')
else:
raise EnvironmentError('Unsupported platform')


result = []
for port in ports:
try:
s = serial.Serial(port)
s.close()
result.append(port)
except (OSError, serial.SerialException):
pass
return result




if __name__ == '__main__':
print(serial_ports())

Thomas 的出色回答的一个可能的改进是,让 Linux 和可能的 OSX 也尝试打开端口,并只返回那些可以打开的端口。这是因为 Linux 至少在/dev/中列出了一大堆端口作为文件,这些文件没有连接到任何东西。如果您在终端中运行,/dev/tty 就是您在其中工作、打开和关闭的终端,它可能会使您的命令行出错,因此通用程序的设计就不会这样做。密码:

    # ... Windows code unchanged ...


elif sys.platform.startswith ('linux'):
temp_list = glob.glob ('/dev/tty[A-Za-z]*')


result = []
for a_port in temp_list:


try:
s = serial.Serial(a_port)
s.close()
result.append(a_port)
except serial.SerialException:
pass


return result

Thomas 代码的这个修改只在 Ubuntu 14.04上测试过。

你可使用:

python -c "import serial.tools.list_ports;print serial.tools.list_ports.comports()"

按已知端口过滤: python -c "import serial.tools.list_ports;print [port for port in serial.tools.list_ports.comports() if port[2] != 'n/a']"

点击这里查看更多信息: Https://pyserial.readthedocs.org/en/latest/tools.html#module-serial.tools.list_ports

moylop260答案的改进:

import serial.tools.list_ports
comlist = serial.tools.list_ports.comports()
connected = []
for element in comlist:
connected.append(element.device)
print("Connected COM ports: " + str(connected))

这列出了硬件中存在的端口,包括正在使用的端口。根据 工具文档,列表中存在更多的信息

Please, try this code:

import serial
ports = serial.tools.list_ports.comports(include_links=False)
for port in ports :
print(port.device)

首先,你需要为串口通信导入包, 所以:

import serial

然后创建当前可用串行端口的列表:

ports = serial.tools.list_ports.comports(include_links=False)

然后,沿着整个列表走,您可以打印端口名称:

for port in ports :
print(port.device)

这只是一个如何获取端口列表并打印它们的名称的示例,但是您可以使用其他一些选项来处理这些数据。之后试试打印不同的变体

port.

基本上已经在文档中提到了这一点 Https://pyserial.readthedocs.io/en/latest/tools.html#module-serial.tools.list_ports

import serial.tools.list_ports
ports = serial.tools.list_ports.comports()


for port, desc, hwid in sorted(ports):
print("{}: {} [{}]".format(port, desc, hwid))

结果:

通讯端口(COM1)[ ACPI PNP05011]

COM7: MediaTek USB 端口(COM7)[ USB VID: PID = 0E8D: 0003 SER = 6 LOCATION = 1-2.1]

一行解决方案与 pySerial 软件包。

python -m serial.tools.list_ports

试试这个代码

import serial.tools.list_ports
for i in serial.tools.list_ports.comports():
print(i)

它回来了

COM1 - Port de communication (COM1)
COM5 - USB-SERIAL CH340 (COM5)

如果您只是不知道例如 COM1的端口名称

import serial.tools.list_ports
for i in serial.tools.list_ports.comports():
print(str(i).split(" ")[0])

它回来了

COM1
COM5

就像我的情况一样 Py 3.764位

只适用于 Windows:

import winreg
import itertools


def serial_ports() -> list:
path = 'HARDWARE\\DEVICEMAP\\SERIALCOMM'
key = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, path)


ports = []
for i in itertools.count():
try:
ports.append(winreg.EnumValue(key, i)[1])
except EnvironmentError:
break


return ports


if __name__ == "__main__":
ports = serial_ports()

可能会迟到,但可能会帮助需要帮助的人。

import serial.tools.list_ports




class COMPorts:


def __init__(self, data: list):
self.data = data


@classmethod
def get_com_ports(cls):
data = []
ports = list(serial.tools.list_ports.comports())


for port_ in ports:
obj = Object(data=dict({"device": port_.device, "description": port_.description.split("(")[0].strip()}))
data.append(obj)


return cls(data=data)


@staticmethod
def get_description_by_device(device: str):
for port_ in COMPorts.get_com_ports().data:
if port_.device == device:
return port_.description


@staticmethod
def get_device_by_description(description: str):
for port_ in COMPorts.get_com_ports().data:
if port_.description == description:
return port_.device




class Object:
def __init__(self, data: dict):
self.data = data
self.device = data.get("device")
self.description = data.get("description")




if __name__ == "__main__":
for port in COMPorts.get_com_ports().data:
print(port.device)
print(port.description)


print(COMPorts.get_device_by_description(description="Arduino Leonardo"))
print(COMPorts.get_description_by_device(device="COM3"))

一些简单的东西,但我使用它很多。

import serial.tools.list_ports as ports


com_ports = list(ports.comports()) # create a list of com ['COM1','COM2']
for i in com_ports:
print(i.device) # returns 'COMx'

需要注意的是,这样的代码:

for i in serial.tools.list_ports.comports():
print(i)

返回以下资料:

COM7 - Standard Serial over Bluetooth link (COM7) COM1 - Communications Port (COM1) COM8 - Standard Serial over Bluetooth link (COM8) COM4 - USB-SERIAL CH340 (COM4)

如果您希望按顺序列出端口,并且只列出可用的端口,请尝试: (归功于 tfeldmann)

   def serial_ports():
""" Lists serial port names


:raises EnvironmentError:
On unsupported or unknown platforms
:returns:
A list of the serial ports available on the system
"""
if sys.platform.startswith('win'):
ports = ['COM%s' % (i + 1) for i in range(256)]
elif sys.platform.startswith('linux') or sys.platform.startswith('cygwin'):
# this excludes your current terminal "/dev/tty"
ports = glob.glob('/dev/tty[A-Za-z]*')
elif sys.platform.startswith('darwin'):
ports = glob.glob('/dev/tty.*')
else:
raise EnvironmentError('Unsupported platform')


result = []
for port in ports:
try:
s = serial.Serial(port)
s.close()
result.append(port)
except (OSError, serial.SerialException):
pass
return result

这将返回以下结果:

['COM1', 'COM4', 'COM8']

因此,与第一个例子中的结果是[‘ COM7’,‘ COM1’,‘ COM8’,‘ COM4’]不同,这次我按顺序得到了所有的 com 端口,并且只有那些可用的端口。如果你需要的话非常方便,可以测试看看是否有。