使用Python列出可用的com端口

doo*_*oom 70 python pyserial

我正在寻找一种简单的方法来列出PC上所有可用的COM端口.

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

我在Windows 7 PC上使用Python 3和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()))
Run Code Online (Sandbox Code Playgroud)

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

你知道为什么它不起作用吗?您是否有另一种不是系统特定的解决方案?

Tho*_*mas 135

这是我使用的代码.

使用Python 2和Python 3在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上成功测试.

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())
Run Code Online (Sandbox Code Playgroud)

  • 如果端口已经打开会发生什么?它会返回错误吗?但港口仍然可用.我只是想知道如何使用python在Windows上建立可行的COM端口断开连接. (3认同)

moy*_*260 24

您可以使用:

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

  • -1; OP 已经提到了 `serial.tools.list_ports.comports()` 并解释说它在提问者的平台上无法正常工作。您没有添加问题中没有的信息。 (2认同)

小智 11

对托马斯的出色答案的一个可能的改进是让Linux和OSX也尝试打开端口并只返回那些可以打开的端口.这是因为Linux至少将一大堆端口列为/ dev /中没有连接任何东西的文件.如果你在一个终端上运行,/ dev/tty是你正在工作的终端,打开和关闭它可能会搞砸你的命令行,所以glob的目的不是那么做.码:

    # ... 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
Run Code Online (Sandbox Code Playgroud)

对Thomas的代码的修改仅在Ubuntu 14.04上进行了测试.


I a*_*... 9

pySerial 包的单行解决方案。

python -m serial.tools.list_ports
Run Code Online (Sandbox Code Playgroud)


gra*_*mbo 6

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))
Run Code Online (Sandbox Code Playgroud)

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

  • 对于那些在嵌入式C中花费1/2的职业生涯的人来说,我不是单行的人在这里做的一切风格.你当然可以在一条线上完成所有工作.我已经纠正了'list'的失礼,不知道我是怎么错过了那些明显的东西.干杯. (5认同)
  • -1至少有几个原因:覆盖像`list`这样的内置函数的名称是不好的做法,你的`connected`的四语句结构可以写得更简洁,因为`connected = [port.device for port在serial.tools.list_ports.comports()]`中. (3认同)
  • @马克·阿默里(Mark Amery)。您真的认为单行代码是问答网站的好主意吗? (3认同)
  • @马克·艾弗里(Mark Avery)。单行代码模糊了新手用户的关键概念。例如,如果您使用列表理解来演示一个简单的概念,那么新手可能会迷失在列表理解中而错过基本概念。如果列表理解是最好的方法,请先显示长手版本,然后再将其缩短。您可以教导自己的观点,并同时增强列表组合。 (2认同)

小智 6

基本上在pyserial文档 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))
Run Code Online (Sandbox Code Playgroud)

结果:

COM1:通信端口(COM1)[ACPI \ PNP0501 \ 1]

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


Mal*_*Who 6

可能晚了,但可能会帮助有需要的人。

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"))
Run Code Online (Sandbox Code Playgroud)


Hip*_*ray 0

有多种选择:

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

使用GUID_DEVINTERFACE_COMPORT 的 ClassGuid 调用SetupDiGetClassDevs 。

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

在win32 新闻组和 CodeProject,呃,项目上有一些对话。

  • -1; 这是一个要求与平台无关的解决方案的 Python 问题,而您已经给出了特定于 Windows 的答案,并且没有给出具体如何在 Python 中执行任何操作的指示。对于一个稍微不同的问题,这可能是一个很好的答案,但在这里不合适。 (3认同)