¿Cuál es el método multiplataforma para enumerar puertos serie en Python (incluidos los puertos virtuales)?

Nota: Estoy usando Python 2.7, y pySerial para comunicaciones seriales.

Encontré este artículo que enumera dos formas: http://www.zaber.com/wiki/Software/Python#Displaying_a_list_of_available_serial_ports

Este método funciona en Windows y Linux, pero a veces pierde puertos virtuales en Linux:

import serial def scan(): # scan for available ports. return a list of tuples (num, name) available = [] for i in range(256): try: s = serial.Serial(i) available.append( (i, s.portstr)) s.close() except serial.SerialException: pass return available print "Found ports:" for n,s in scan(): print "(%d) %s" % (n,s) 

Y este que solo funciona en Linux, pero incluye puertos virtuales:

 import serial, glob def scan(): # scan for available ports. return a list of device names. return glob.glob('/dev/ttyS*') + glob.glob('/dev/ttyUSB*') print "Found ports:" for name in scan(): print name 

Supongo que podría hacer una detección de plataforma para usar el segundo método (el que incluye puertos virtuales) cuando se ejecuta en Linux, y el primer método cuando se ejecuta Windows, pero ¿qué pasa con Mac?

¿Cómo debo enumerar los puertos serie (virtuales también) independientemente de la plataforma?

Editar

Encontré algunas preguntas pertinentes:

  • MacPython: encontrando programáticamente todos los puertos seriales
  • MacOS: ¿cuál es la diferencia entre /dev/tty.* y /dev/cu.*?
  • ¿Cómo encontrar todos los dispositivos serie (ttyS, ttyUSB, ..) en Linux sin abrirlos?

Esto es lo que he estado usando. Es una combinación de los métodos que publiqué anteriormente. Sin embargo, todavía me gustaría ver mejores soluciones.

 # A function that tries to list serial ports on most common platforms def list_serial_ports(): system_name = platform.system() if system_name == "Windows": # Scan for available ports. available = [] for i in range(256): try: s = serial.Serial(i) available.append(i) s.close() except serial.SerialException: pass return available elif system_name == "Darwin": # Mac return glob.glob('/dev/tty*') + glob.glob('/dev/cu*') else: # Assume Linux or something else return glob.glob('/dev/ttyS*') + glob.glob('/dev/ttyUSB*') 

bitpim tenía bastante código para comscan en múltiples plataformas. Probablemente sea útil obtener algo de código para construir un enumerador de puertos serie multiplataforma. Puede ejecutar el código de detección directamente en la línea de comandos para probarlo.

Enlace al archivo fuente comscan.py .

En Linux, no parece detectar puertos ‘/ dev / ttyS’. Añadiendo la siguiente línea debajo de la línea # 378 trabajada:

 ("/dev/ttyS", "Standard Serial Port", "serial"), 

El autor ha facilitado la adición de diferentes tipos de identificadores para los puertos serie.

En Mac, funcionó bien. (Tenía un Arduino a la mano para probar)

En Windows, detectó correctamente el puerto conectado (para el conector FTDI conectado). Requiere pywin32 .

Con pyserial , probé lo siguiente:

python -m serial.tools.list_ports

No parece funcionar en Windows. Funciona en Mac. Funciona en Linux.

Es interesante ver la sección de la Plataforma en la documentación para este comando :

 Platform : Posix (/dev files) Platform : Linux (/dev files, sysfs and lsusb) Platform : Windows (setupapi, registry) 

Creo que una fusión de los dos debería dar un enumerador de puertos de comunicaciones (casi) confiable.

Edición : Probé todo lo anterior en Python 2.7.

¿La función de usuario, serial.tools.list_ports , le da lo que quiere?

No sé si todavía está buscando respuestas a esto, pero como tengo una solución de trabajo, pensé en publicarla. Aquí está el paquete de getports como parte de mi proyecto Arduino Data Logger. Lo he probado para que funcione en Mac, al menos en algunas versiones de Linux y Windows 7. A diferencia de comscan de bitpim, no utiliza ningún módulo que no sea de la biblioteca estándar. Además, no usa /dev globbing en Linux o Mac, por lo que cambiar las reglas no debería ser un problema. (En Linux usa sysfs y en Mac usa IOKit). No sé si detecta puertos seriales virtuales en Linux, pero si no lo hace, intente reemplazar

 sys_suffix = '/device/' 

con

 sys_suffix = '' 

en linuxgetports.py