Python으로 사용 가능한 com 포트 나열


86

PC에서 사용 가능한 모든 COM 포트를 나열하는 간단한 방법을 찾고 있습니다.

이 방법을 찾았지만 Windows 전용입니다. Windows에서 직렬 (COM) 포트 나열?

Windows 7 PC에서 pySerial과 함께 Python 3을 사용하고 있습니다.

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 to COM 게이트웨이가 PC에 연결되어있을 때 (장치 관리자에 COM5가 표시됨)이 COM 포트는에서 반환 된 목록에 포함되지 않습니다 list_ports.comports(). 대신 모뎀에 연결된 것처럼 보이는 COM4 만 얻습니다 (장치 관리자의 COM & LPT 섹션에는 표시되지 않습니다)!

왜 작동하지 않는지 아십니까? 특정 시스템이 아닌 다른 솔루션이 있습니까?


21
새로운 독자 :이 질문을받은 지 5 년이 넘었으며이 comports()질문에 설명 된 pySerial 함수 의 버그 (복제 방법에 대한 정확한 정보없이)가 수정되었을 수 있습니다. 시도하여 시작하십시오 import serial.tools.list_ports; print([comport.device for comport in serial.tools.list_ports.comports()]). 그것이 당신에게 효과가없는 경우에만 당신과 관련된 아래 답변 중 하나가 있습니다.
마크 Amery

또한 새로운 독자들에게 : 분명히 pySerial의 변경으로 인해 OP (및 일부 답변)에 의해 설명 된 코드는 더 이상 완전하거나 불완전한 COM 포트 이름 목록을 생성하지 않습니다. 대신 개체에 대한 개체 참조 목록을 생성 ListPortInfo합니다. 이름이나 기타 정보를 얻으려면 목록을 작성할 때 이러한 개체의 속성을 사용해야합니다. 참조 : pythonhosted.org/pyserial/…
JDM

답변:


155

이것이 제가 사용하는 코드입니다.

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())

여기에 시스템 버전 감지 기능을 추가하여 하루라고 할 수 있습니다. OS에 따라 포트가 다르게 획득된다는 점에서 "모든 시스템"이 동일하다는 사실을 알지 못합니다. 간단히 OS 버전을 감지 한 다음이를 기반으로 다양한 경우에 사용할 수있는 스위치가 있습니다.
jml 2013

1
except OSError: passOSX에서 테스트 할 때도 추가해야했습니다 .
nvahalik 2014-08-14

4
포트가 이미 열려 있으면 어떻게됩니까? 바로 오류를 반환합니까? 그러나 포트는 여전히 사용할 수 있습니다. 파이썬으로 Windows에서 실행 가능한 COM 포트 연결을 끊는 방법을 궁금합니다.
Manny42 2015

@ Manny42 나는 당신이 성취하려는 것을 이해하지 못하지만, 포트가 이미 열려 있다면 분명히 다른 프로그램에서 사용할 수 없으며 serial_ports()함수 에 의해 나열 되지 않을 것입니다 (예외를 발생시키지 않을 것입니다). close()pyserial에서 제공 하는 함수 를 사용하여 COM 포트 연결을 끊지 않는 이유는 무엇 입니까?
tfeldmann 2015

@Thomas - 포트 aswell의 몇 가지 설명을 얻을 수있는 방법이 나는 설명에 따라 내 선택의 포트 선택 할 필요가

25

당신이 사용할 수있는:

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를 참조 하십시오.


이것은 파이썬 2.7.11을 사용하는 OSX 10.11.5에서 훌륭하게 작동하며 Thomas의 솔루션보다 훨씬 빠른 것 같습니다. Python 3.4.4가 설치된 OSX 10.11.5에서는 빈 배열을 반환하므로 일부 com 포트가 누락되었습니다.
doizuc

Windows7 및 Python 2.7에서 잘 작동합니다. 매우 유용하게도 ('COM114', 'USB Serial Port (COM114)', 'FTDIBUS\\VID_0403+PID_6001+7&2A8DEF85&0&2\\0000')다음 과 같은 튜플을 반환합니다. 이로써 공급 업체 USB PID / VID로 필터링 할 수 있습니다.
Richard Aplin

Linux 보드 (Debian, 3.4 커널)에서 테스트 한 결과 똑같이 좋은 결과를 얻었습니다. 이번에는 USB 장치 일련 번호 ('/dev/ttyACM1', 'ttyACM1', 'USB VID:PID=0483:5752 SNR=8D7B179D5354')Great solution을 포함합니다. 고마워!
Richard Aplin

여기에 매우 유사한 답변이 있습니다 : stackoverflow.com/questions/24214643/…
Gladclef

2
-1; OP는 이미 언급 serial.tools.list_ports.comports()하고 asker의 플랫폼에서 올바르게 작동하지 않는다고 설명했습니다. 질문에없는 정보를 추가하지 않습니다.
마크 Amery


11

Thomas의 훌륭한 대답에 대한 가능한 개선은 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

Thomas의 코드에 대한이 수정은 Ubuntu 14.04에서만 테스트되었습니다.


8

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))

여기에는 사용중인 포트를 포함하여 하드웨어에 존재하는 포트가 나열됩니다. pyserial 도구 문서 에 따라 훨씬 더 많은 정보가 목록에 있습니다.


3
적어도 몇 가지 이유 때문에 -1 : 같은 내장의 이름을 재정의하는 것은 나쁜 습관 list이며,의 4 개 문 구성은 connected훨씬 더 간결하게 connected = [port.device for port in serial.tools.list_ports.comports()].
마크 아메리

5
임베디드 C에서 경력의 1/2을 보냈던 사람에게, 나는 여기에서 모든 일을하는 한 줄의 사람이 아닙니다. 한 줄로 모두 할 수 있습니다. 나는 '목록'가짜 파스를 수정했지만 어떻게 그렇게 눈부신 것을 놓쳤는 지 확실하지 않습니다. 건배.
grambo

3
@ Mark Amery. 질문 및 답변 사이트에 대해 한 줄짜리가 정말 좋은 생각이라고 생각하십니까?
cstrutton

@cstrutton 귀하의 질문을 이해하지 못합니다.
Mark Amery

2
@ 마크 에이버리. 한 줄짜리는 초보 사용자의 핵심 개념을 모호하게합니다. 예를 들어, 간단한 개념을 보여주기 위해 목록 이해력을 사용하면 초보자는 목록 이해력에서 길을 잃고 기본 개념을 놓칠 수 있습니다. 목록을 이해하는 것이 가장 좋은 방법이라면 먼저 긴 손 버전을 보여준 다음 그것을 줄이는 방법을 보여줍니다. 당신은 당신의 요점을 가르치고 동시에 목록을 강화합니다.
cstrutton


2

이 코드를 시도하십시오 :

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)

이것은 포트 목록을 가져오고 이름을 인쇄하는 방법의 예일 뿐이지 만이 데이터로 수행 할 수있는 다른 옵션이 있습니다. 이후에 다른 변형을 인쇄 해보십시오.

포트.


나는 당신이 import serial.tools.list_ports를해야한다고 생각한다. 또는 적어도 그것은 내가 PySerial 3.4를 사용하는 Python 3.7에서 시리얼의 내 버전에서
해야하는

0

몇 가지 옵션을 사용할 수 있습니다.

NULL lpDeviceName을 사용하여 QueryDosDevice 를 호출 하여 모든 DOS 장치를 나열합니다. 그런 다음 각 장치 이름과 함께 CreateFile 및 GetCommConfig 를 차례로 사용하여 직렬 포트인지 확인합니다.

GUID_DEVINTERFACE_COMPORT의 ClassGuid를 사용하여 SetupDiGetClassDevs 를 호출합니다 .

WMI는 C / C ++ 프로그램에서도 사용할 수 있습니다 .

win32 뉴스 그룹 과 CodeProject, er, project 에 대한 대화가 있습니다 .


3
-1; 이것은 플랫폼에 구애받지 않는 솔루션을 요구하는 Python 질문이었으며 Windows 관련 답변으로 응답했으며 특히 Python에서이 작업을 수행하는 방법에 대한 표시를 제공하지 않았습니다. 이것은 약간 다른 질문에 대한 훌륭한 대답이 될 수 있지만 여기에서는 적절하지 않습니다.
마크 Amery

0

이 코드를 시도

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.7 64bits


0

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()
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.