我试图从python中的多个串口读取。但与this线程相反,我希望能够动态更改端口数(通过命令行选项读取)。
我的想法是将端口放入文件" ports",读取此文件并将打开的串口放入列表中,根据"端口"中的行数。 。我的最小例子:
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)以有用的方式解决多端口问题?提前谢谢。
答案 0 :(得分: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&gt; = 3.4,selectors
模块。您不需要多个进程来执行此操作。
如果应用程序受CPU限制,那么您可以使用mutiprocessing.Process()
或subprocess.Popen()
。不是打开父节点中的串行端口,而是将串行端口参数作为子函数/进程的参数/命令行参数传递给子节点,让子节点打开端口,处理数据并关闭端口。
<强> N.B。未经测试 - 不知道这是否适用于串口。如果必须打开父级中的端口,请将子进程的stdin挂接到串行端口。你需要小心这一点,因为很容易发生死锁过程,父母和孩子互相阻塞。
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 :(得分: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-array的方法是:
>>> 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')
但我不确定如果那就是你要找的东西。