2016-09-27 111 views
0

我想从多个串行端口读取python。但与this线程相反,我希望能够动态更改端口数(通过命令行选项读取它)。python读取多个串行端口

我的想法是将端口放入文件“端口”,根据“端口”中的行数读取此文件并将打开的串行端口放入列表中。我的小例子:

import numpy as np 
import serial 

p = np.genfromtxt('ports',delimiter=',',dtype=None) 
nser = p.size 

ser = [serial.Serial(port=p[i][0], baudrate=p[i][1]) for i in xrange(nser)] 

“端口” 看上去以下(目前):

'/dev/ttyUSB0',4800 

错误:

Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
IndexError: 0-d arrays can't be indexed 

显然,文件不正确读取到一个数组,我已经尝试了各种不同的方法和方法(使用pythons自己的方法或np.loadtxt)。

有没有人有一个想法如何a)正确读取文件和b)以有用的方式解决多端口问题?提前致谢。

回答

2

你的配置文件格式非常简单,可以很容易地解析没有numpy。您可以使用简单的字符串拆分来加载每个端口定义。

serial_ports = [] 
with open('ports') as f: 
    for line in f: 
     port, baud = line.split(',') 
     serial_ports.append(serial.Serial(port, int(baud))) 

或者你可以使用csv模块:

import csv 

with open('ports') as f: 
    serial_ports = [serial.Serial(port, int(baud)) for port, baud in csv.reader(f)] 

,因为您没有提供有关串口的读者会如何处理很多细节你问题的第二部分是比较难通过端口接收的数据。

如果应用程序是I/O绑定的,这很可能是这种情况,您可以异步检查串行端口何时读取一些数据,然后根据需要读取它。这可以通过select()模块完成,或者如果您使用的是Python> = 3.4,则可以使用selectors模块。您不需要多个进程来执行此操作。

如果应用程序受CPU限制,则可以使用mutiprocessing.Process()subprocess.Popen()。而不是打开父级的串行端口,将串行端口参数作为参数/命令行参数传递给子级函数/进程,并让子级打开端口,处理数据并关闭端口。

N.B.未经测试 - 不知道这是否适用于串口。如果您必须打开父进程中的端口,请将子进程的标准输入连接到串行端口。你需要小心这一点,因为父母和孩子彼此相互阻塞的过程很容易发生死锁。

from subprocess import Popen, PIPE 

s = serial.Serial(port, baud) 
p = Popen(['python', 'port_reader.py'], stdin=s, stdout=PIPE, stderr=PIPE) 
p.communicate() 

如果使用multiprocessing您可以打开串口传给孩子作为参数。这可能工作...?

from multiprocessing import Process 

def child(port): 
    while True: 
     line = port.readline() 
     if not line: 
      break 
     print('child(): read line: {!r}'.format(line)) 

port = serial.Serial(port, baud) 
p = Process(target=child, args=(port,)) 
p.start() 
p.join() 
1

我不太清楚理解你正在尝试做的,但如果 我有过一个文件:

'/dev/ttyUSB0',4800 
'/dev/ttyUSB1',4801,'/dev/ttyUSB3',4803 

,并希望阅读和存储作为一个列表,很长的路要走会是:

with open('ports.txt') as f: 
    lines = f.read().replace('\n', ',') 
print lines 

,这将给你:

>>> lines 
'/dev/ttyUSB0',4800,'/dev/ttyUSB1',4801,'/dev/ttyUSB3',4803 

,如果要拆分整数,你可以这样做:

>>> l1 = [lines.pop(i) for i,j in enumerate(lines) if type(j)==int ] 
>>> l1 
[4800, 4801, 4803] 
>>> lines 
['/dev/ttyUSB0', '/dev/ttyUSB1', '/dev/ttyUSB3'] 

现在,因为你说,“np.loadtxt”没有工作,这是一种以Python列表转换为numpy的阵列是:

>>> lines = ['/dev/ttyUSB0',4800,'/dev/ttyUSB1',4801,'/dev/ttyUSB3',4803] 
>>> 
>>> import numpy as np 
>>> np.asarray(lines) 
array(['/dev/ttyUSB0', '4800', '/dev/ttyUSB1', '4801', '/dev/ttyUSB3', 
     '4803'], 
     dtype='|S12') 

但是,我不确定如果那是你想要的。