如何在python中使用多处理读取串行数据? [英] How to read serial data with multiprocessing in python?
问题描述
我有一个以不规则间隔输出数据的设备.我想以 2 秒的间隔将数据写入 csv.所以我认为使用队列进行多处理可能会奏效.
I have a device that outputs data at irregular intervals. I want to write data onto a csv in 2 second intervals. So I figured multiprocessing with a queue might work.
在这里,我试图将数据从一个进程传递到另一个进程,但出现串行异常.另外,我无法在 IDLE 上运行它.所以我坚持使用终端.结果,错误消息一打开就关闭.
Here I'm trying to just pass data from one process to another but I get Serial Exception. Also, I'm unable to run it on IDLE. So I'm stuck with using the terminal. As a result, the error message closes as soon as it opens.
代码如下:
import multiprocessing
import time
import datetime
import serial
try:
fio2_ser = serial.Serial("COM3",
baudrate=2400,
bytesize=serial.EIGHTBITS,
parity =serial.PARITY_ODD)
except serial.SerialException:
print("FiO2 Analyser Device not detected")
def Read_Data(q):
global fio2_ser
while True:
try:
fio2_data = fio2_ser.readline().decode('utf-8')
fio2_data = str(fio2_data).replace("\r\n","")
fio2_data = fio2_data.replace("\x000","")
except:
fio2_data = "FiO2 Data Unavailable"
q.put(fio2_data)
def Disp_Data(q):
while q.empty() is False:
fio2_data = q.get()
print(fio2_data)
time.sleep(2)
if __name__ == "__main__":
q = multiprocessing.Queue()
p1 = multiprocessing.Process(target=Read_Data, args=(q,))
p2 = multiprocessing.Process(target=Disp_Data, args=(q,))
p1.start()
p2.start()
p1.join()
p2.join()
当我运行一个单独的模块来收集数据时,它运行良好并收集数据.
When I run a separate module to collect data, it runs fine and collects data.
import serial
try:
fio2_ser = serial.Serial("COM3",
baudrate=2400,
bytesize=serial.EIGHTBITS,
parity =serial.PARITY_ODD)
except serial.SerialException:
print("FiO2 Analyser Device not detected")
def Reader():
global fio2_ser
try:
fio2_data = fio2_ser.readline().decode('utf-8')
fio2_data = str(fio2_data).replace("\r\n","")
fio2_data = fio2_data.replace("\x000","")
return fio2_data
except:
return "FiO2 Data Unavailable"
if __name__ =='__main__':
value = Reader()
print(value)
推荐答案
当 q.empty() 为 True 时,Disp_Data() 函数将停止运行.在我的情况下,循环立即退出.
The Disp_Data() function will stop running when q.empty() is True. In my case the loop exits immediately.
可能有助于显示 SerialException 抛出的错误消息以查看原因:
Might be useful to display the error message thrown by SerialException to see the cause:
except serial.SerialException as msg:
print( "Error opening serial port %s" % msg)
此外,最好优雅地关闭子进程.就我而言,它们在杀死主进程后继续运行,因此 Read_Data() 进程保持端口打开.
Also, it would be better to gracefully shut down the child-processes. In my case, they kept running after killing the main process, so the Read_Data() process keeps the port open.
多处理模块不喜欢酸洗 pyserial.
以下代码片段适用于我的 Windows10 机器
This following code snip works on my Windows10 box
- 改用线程.
- 在此处添加了一些打印语句,以了解什么是正在发生.
- 使用 multiprocessing.Event() 来改进关闭.
- 打印异常错误消息以查看导致串行异常的原因.
- 串行端口上的一秒超时以允许读取循环继续.
- 发布代码可能不需要.
import threading, multiprocessing import time import serial import sys def OpenSerialPort(port=""): print ("Open port %s" % port) fio2_ser = None try: fio2_ser = serial.Serial(port, baudrate=2400, bytesize=serial.EIGHTBITS, parity =serial.PARITY_ODD) except serial.SerialException as msg: print( "Error opening serial port %s" % msg) except: exctype, errorMsg = sys.exc_info()[:2] print ("%s %s" % (errorMsg, exctype)) return fio2_ser def Read_Data(queue, serialPort, stopped): print ("Start reading data.") serialPort.timeout = 1.0 while not stopped.is_set(): fio2_data = '' try: #print "Reading port..." fio2_data = serialPort.readline() except: exctype, errorMsg = sys.exc_info()[:2] print ("Error reading port - %s" % errorMsg) stopped.set() break if len(fio2_data) > 0: fio2_data = fio2_data.decode('utf-8') fio2_data = str(fio2_data).replace("\r\n","") fio2_data = fio2_data.replace("\x000","") queue.put(fio2_data) else: queue.put("Read_Data() no Data") serialPort.close() print ("Read_Data finished.") def Disp_Data(queue, stopped): print ("Disp_Data started") while not stopped.is_set(): #print "Check message queue." if queue.empty() == False: fio2_data = queue.get() print(fio2_data) print ("Disp_Data finished") if __name__ == "__main__": #serialPort = OpenSerialPort('/dev/ttyUSB0') serialPort = OpenSerialPort('COM3') if serialPort == None: sys.exit(1) queue = multiprocessing.Queue() stopped = threading.Event() p1 = threading.Thread(target=Read_Data, args=(queue, serialPort, stopped,)) p2 = threading.Thread(target=Disp_Data, args=(queue, stopped,)) p1.start() p2.start() loopcnt = 20 while (loopcnt > 0) and (not stopped.is_set()): loopcnt -= 1 print ("main() %d" % loopcnt) try: time.sleep(1) except KeyboardInterrupt: #Capture Ctrl-C print ("Captured Ctrl-C") loopcnt=0 stopped.set() stopped.set() loopcnt=0 print ("Stopped") p1.join() p2.join() serialPort.close() print ("Done")
这篇关于如何在python中使用多处理读取串行数据?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!