python读取多个串口
python read multiple serial ports
我正在尝试从 python 中的多个串行端口读取数据。但与 this 线程相反,我希望能够动态更改端口数(通过命令行选项读取)。
我的想法是把串口放到一个文件"ports"中,读取这个文件,把打开的串口按照"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)]
"ports" 看起来如下(目前):
'/dev/ttyUSB0',4800
错误:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
IndexError: 0-d arrays can't be indexed
显然文件没有正确读取到数组,我已经尝试了各种不同的方法和方式(使用python自己的方法或np.loadtxt)。
有没有人知道如何 a) 正确读取文件和 b) 以有用的方式解决多端口问题?提前致谢。
我不是很清楚你想做什么,但是如果
我有一个这样的文件:
'/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')
但我还是不确定这是否是您要找的。
你的配置文件格式非常简单,不用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()
module, or if you're using Python >= 3.4, the selectors
模块来完成。您不需要多个进程来执行此操作。
如果应用程序是 CPU 绑定的,那么您可以使用 mutiprocessing.Process()
或 subprocess.Popen()
。不要在 parent 中打开串行端口,而是将串行端口参数作为 arguments/command 行参数传递给 child child function/process 并让 child打开端口,处理数据,关闭端口。
N.B。未经测试 - 不知道这是否适用于串行端口。如果您必须打开 parent 中的端口,请将子进程的标准输入连接到串行端口。您需要注意这一点,因为 parent 和 child 相互阻塞的进程很容易死锁。
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
,您可以将打开的串行端口作为参数传递给 child。这可能有用...?
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()
我正在尝试从 python 中的多个串行端口读取数据。但与 this 线程相反,我希望能够动态更改端口数(通过命令行选项读取)。
我的想法是把串口放到一个文件"ports"中,读取这个文件,把打开的串口按照"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)]
"ports" 看起来如下(目前):
'/dev/ttyUSB0',4800
错误:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
IndexError: 0-d arrays can't be indexed
显然文件没有正确读取到数组,我已经尝试了各种不同的方法和方式(使用python自己的方法或np.loadtxt)。
有没有人知道如何 a) 正确读取文件和 b) 以有用的方式解决多端口问题?提前致谢。
我不是很清楚你想做什么,但是如果 我有一个这样的文件:
'/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')
但我还是不确定这是否是您要找的。
你的配置文件格式非常简单,不用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()
module, or if you're using Python >= 3.4, the selectors
模块来完成。您不需要多个进程来执行此操作。
如果应用程序是 CPU 绑定的,那么您可以使用 mutiprocessing.Process()
或 subprocess.Popen()
。不要在 parent 中打开串行端口,而是将串行端口参数作为 arguments/command 行参数传递给 child child function/process 并让 child打开端口,处理数据,关闭端口。
N.B。未经测试 - 不知道这是否适用于串行端口。如果您必须打开 parent 中的端口,请将子进程的标准输入连接到串行端口。您需要注意这一点,因为 parent 和 child 相互阻塞的进程很容易死锁。
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
,您可以将打开的串行端口作为参数传递给 child。这可能有用...?
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()