Pythonで利用可能なCOMポートを一覧表示する


86

PCで利用可能なすべてのCOMポートを一覧表示する簡単な方法を探しています。

私はこの方法を見つけましたが、それはWindows固有です:Windowsのシリアル(COM)ポートを一覧表示しますか?

私はWindows7PCでpySerialとともにPython3を使用しています。

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()])ます。それがうまくいかない場合にのみ、以下の回答のいずれかがあなたに関連しています。
マークアメリー2017

また、新しい読者の方へ:明らかにpySerialの変更により、OPによって記述されたコード(および一部の回答)は、完全か不完全かにかかわらず、COMポート名のリストを生成しなくなりました。代わりに、オブジェクトへのオブジェクト参照のリストを生成しListPortInfoます。名前やその他の情報を取得するには、リストを作成するときにこれらのオブジェクトの属性を使用する必要があります。参照: pythonhosted.org/pyserial/…–
JDM

回答:


155

これは私が使用するコードです。

Python2とPython3の両方を使用して、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())

これにいくつかのシステムバージョン検出を追加して、それを1日と呼ぶかもしれません。OSによってポートの取得方法が異なるという点で、「すべてのシステム」が同じであることに気づいていません。OSのバージョンを検出するだけで、それに基づいてさまざまなケースで使用できるスイッチがあります。
jml 2013

1
except OSError: passOSXでテストするときにも追加する必要がありました。
nvahalik 2014

4
ポートがすでに開いている場合はどうなりますか?エラーが返されますよね?ただし、ポートは引き続き使用できます。Pythonを使用してWindowsで実行可能なCOMポートの接続を解除する方法を考えています。
manny42 2015年

@ Manny42何を達成しようとしているのかわかりませんが、ポートがすでに開かれている場合、他のプログラムでは使用できず、serial_ports()関数によってリストされません(例外は発生しません)。close()pyserialが提供する機能を使ってCOMポートを外してみませんか?
tfeldmann 2015年

@ Thomas-ポートの説明も取得する方法はありますか?説明に基づいて選択したポートを選択する必要があります

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をご覧ください。


これは、Python2.7.11を搭載したOSX10.11.5でうまく機能し、Thomasのソリューションよりもはるかに高速であるようです。Python3.4.4を搭載したOSX10.11.5では、空の配列が返されるため、一部のcomポートが確実に欠落しています。
doizuc 2016年

Windows7とPython2.7でうまく機能します。非常に便利なことに、次のようなタプルが返されます。('COM114', 'USB Serial Port (COM114)', 'FTDIBUS\\VID_0403+PID_6001+7&2A8DEF85&0&2\\0000')これにより、ベンダーのUSB PID / VIDでフィルター処理できます。これは、まさに私が求めていたものです。
リチャードアプリン2016年

Linuxボード(Debian、3.4カーネル)でテストしたところ、同様に良好な結果が得られました。今回はUSBデバイスのシリアル番号を含み('/dev/ttyACM1', 'ttyACM1', 'USB VID:PID=0483:5752 SNR=8D7B179D5354')ます。優れたソリューションです。THX!
リチャードアプリン2016年

非常によく似た答えがここにあります:stackoverflow.com/questions/24214643/...
Gladclef

2
-1; OPはすでに言及serial.tools.list_ports.comports()し、質問者のプラットフォームでは正しく機能しなかったと説明しました。問題に含まれていなかった情報を追加していません。
マークアメリー2017

16

基本的にこれは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))

結果:

COM1:通信ポート(COM1)[ACPI \ PNP0501 \ 1]

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


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のコードに対するこの変更は、Ubuntu14.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には、少なくとも2つの理由がlistあります。のような組み込みの名前をオーバーライドするのは悪い習慣です。また、の4つのステートメントの構成は、のconnectedようにかなり簡潔に記述できますconnected = [port.device for port in serial.tools.list_ports.comports()]
マークアメリー2017

5
エンベデッドCで1/2のキャリアを過ごした人にとって、私はここですべてをスタイルで行う単一のラインの1つではありません。あなたは確かにそれをすべて1行で行うことができます。私は「リスト」の偽物を修正しましたが、そのような明白な何かをどのように見逃したのかわかりません。乾杯。
grambo 2018

3
@マークアメリー。あなたは本当にワンライナーが質疑応答サイトのための良い考えだと思いますか?
cstrutton 2018

@cstruttonあなたの質問がわかりません。
マークアメリー2018

2
@マークエイブリー。ワンライナーは、初心者ユーザーからの重要な概念をあいまいにします。たとえば、リスト内包を使用して単純な概念を示す場合、初心者はリスト内包に迷い、基本概念を見逃す可能性があります。リスト内包表記がそれを行うための最良の方法である場合は、最初に長い手バージョンを示し、次にそれを短くする方法を示します。あなたはあなたのポイントを教え、同時にリストコンプを強化します。
cstrutton 2018


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)

これは、ポートのリストを取得してその名前を出力する方法の単なる例ですが、このデータを使用して実行できる他のオプションがいくつかあります。後で別のバリエーションを印刷してみてください

港。


serial.tools.list_portsをインポートする必要があると思います。少なくとも、PySerial3.4を使用したPython3.7のシリアルのバージョンで行う必要があることです
TomMyddeltyn19年

0

いくつかのオプションが利用可能です:

NULL lpDeviceNameを指定してQueryDosDeviceを呼び出し、すべてのDOSデバイスを一覧表示します。次に、CreateFileとGetCommConfigを各デバイス名で順番に使用して、それがシリアルポートであるかどうかを確認します。

コールSetupDiGetClassDevs GUID_DEVINTERFACE_COMPORTのClassGuidと。

WMIは、C / C ++プログラムでも使用できます

win32ニュースグループとCodeProject、er、projectでいくつかの会話があります。


3
-1; これは、プラットフォームに依存しないソリューションを求めるPythonの質問でした。あなたは、Windows固有の回答で回答しましたが、特にPythonでこれを行う方法を示していません。これは少し異なる質問に対する素晴らしい答えかもしれませんが、ここでは場違いです。
マークアメリー2017

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

私の場合のようにpy3.764ビット


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.