线程挂起或冻结问题

时间:2019-06-29 15:38:55

标签: python multithreading pyserial

我有一个python程序,该程序运行一个线程以从串行端口获取数据。在线程冻结之前,该程序可以正常运行大约1个小时,而我倾向于反复获取最后一组值(在冻结发生之前获取的值)。 是什么原因可能导致线程冻结?

import pynmea2
import serial
import pandas as pd
import threading
import multiprocessing
from datetime import datetime
from dateutil import parser
from analyser import Analysis
import os
import logging
import time


gps_data = {}
arduino_data = {}


def read_serial_arduino(port, baud, ard_key_list):
    ser = serial.Serial()
    ser.port = port

    ser.baudrate = baud
    # ser.bytesize = serial.EIGHTBITS #number of bits per bytes
    # ser.parity = serial.PARITY_NONE #set parity check: no parity
    # ser.stopbits = serial.STOPBITS_ONE #number of stop bits
    # ser.timeout = None          #block read
    # ser.timeout = 0            # non blocking read
    ser.xonxoff = False  # disable software flow control
    ser.rtscts = False  # disable hardware (RTS/CTS) flow control
    ser.dsrdtr = False  # disable hardware (DSR/DTR) flow control
    ser.writeTimeout = 2  # timeout for write

    try:
        ser.open()
    except Exception as e:
        print("error open serial port: " + str(e))
        exit()

    if ser.isOpen():
        try:
            int_index = [0, 4, 5, 6]
            float_index = [1, 2, 3, 6, 7, 8]
            while True:
                c = ser.readline().decode("ascii", "ignore").strip().split(",")

                if len(c) > 1:
                    global arduino_data
                    for i in int_index:
                        c[i] = int(c[i])
                    for j in float_index:
                        c[j] = float(c[j])

                    arduino_data = dict(zip(ard_key_list, c))


            ser.close()

        except Exception as e1:
            print("error...Arduino: " + str(e1))

    else:
        print("cannot open serial port ")
        exit()


def read_serial_gps(port, baud):
    ser = serial.Serial()
    ser.port = port

    ser.baudrate = baud
    # ser.bytesize = serial.EIGHTBITS #number of bits per bytes
    # ser.parity = serial.PARITY_NONE #set parity check: no parity
    # ser.stopbits = serial.STOPBITS_ONE #number of stop bits
    # ser.timeout = None          #block readq
    # ser.timeout = 0            # non blocking read
    ser.xonxoff = False  # disable software flow control
    ser.rtscts = False  # disable hardware (RTS/CTS) flow control
    ser.dsrdtr = False  # disable hardware (DSR/DTR) flow control
    ser.writeTimeout = 2  # timeout for write

    try:
        ser.open()
    except Exception as e:
        print("error open serial port: " + str(e))
        exit()

    if ser.isOpen():
        try:
            while True:
                c = ser.readline().decode('ascii', "ignore")

                # with lock:
                if len(c) > 0:
                    if c.__contains__('$GNRMC'):
                        msg = pynmea2.parse(c)
                        global gps_data
                        gps_data["Latitude"] = round(float(msg.lat[:2]) + float(msg.lat[2:]) / 60, 6)
                        gps_data["Longitude"] = round(float(msg.lon[1:3]) + float(msg.lon[3:]) / 60, 6)
                        gps_data["GPS_Speed"] = msg.spd_over_grnd * 1.852
                        gps_data["Timestamp"] = parser.parse(str(msg.datestamp) + ' ' + str(msg.timestamp))
                        # gps_data["Timestamp"] = msg.timestamp
            ser.close()

        except Exception as e1:
            print("error communicating GPS...: " + str(e1))

    else:
        print("cannot open serial port GPS ")
        exit()


def serial_grab_analyse():
    """
    This Process grabs Serial data from two serial ports and then packs them into a dictionary and appends to a dataframe
    the Data frame is then sent further for analysis.
    :return: No return
    """
    ard_data_key_list = ["GyroX","GyroY", "GyroZ", "APot", "BPot", "CPot"]

    # Thread to grab data from the GPS serially
    g = threading.Thread(target=read_serial_gps,
                         args=('COM3', 9600,))
    g.daemon = True
    g.start()
    # Thread to grab data from Arduino Serially
    y = threading.Thread(target=read_serial_arduino, args=(
    'COM8', 115200, ard_data_key_list,))
    y.daemon = True


    y.start()

    df = pd.DataFrame(columns=ard_data_key_list + ['Latitude', 'Longitude', 'GPS_Speed', 'Timestamp'])

    first_time_stamp = None
    flag_time_stamp = None
    # This while loop keeps the above threads running.
    data_analyser = Analysis()
    while True:
        try:
            captured_data = {**arduino_data, **gps_data}
            # appending a constant speed for testing
            # captured_data['Speed'] = 0.167
            print(captured_data)
            time.sleep(0.02)
            df = df.append(captured_data, ignore_index=True)
            df.dropna(inplace=True)
            print(df)
            if len(df.index):

                speed_var.value = int(float(captured_data["Speed"]))
                if not first_time_stamp:
                    flag_time_stamp = first_time_stamp = df["Timestamp"].iloc[0]

                if (df["Timestamp"].iloc[-1] - flag_time_stamp).seconds >= 60:
                    flag_time_stamp = df["Timestamp"].iloc[-1]
                    data_analyser.analyse(df, first_time_stamp)
                print(g)

            if terminate.value == 1:
                exit(0)
                break

        except Exception as e:
            print(e)



if __name__ == "__main__":

    # Shared value between the two processes to terminate the p2 process when p1 is terminated
    p1 = multiprocessing.Process(target=serial_grab_analyse)
    p1.start()

我正在尝试从两个串行端口(arduino微控制器和GPS设备)读取数据。为此,有两个线程可以无限期运行,我将其放置为一个进程,因为还有另一个进程从网络摄像头获取图片(该进程不在代码段中)。问题在于,连续运行40-50分钟后,GPS读取线程几乎挂起。

0 个答案:

没有答案