多处理功能不写入文件或打印

我正在使用 Raspberry Pi (3 B+) 制作数据收集设备,我正在尝试生成一个进程来记录传入的数据并将其写入文件。我有一个写作函数,当我直接调用它时可以正常工作。


然而,当我使用多进程方法调用它时,似乎什么也没发生。我可以在 Linux 的任务监视器中看到该进程确实被生成但没有文件被写入,并且当我尝试将标志传递给它以关闭它时它不起作用,这意味着我最终终止了该进程而什么也没有似乎已经发生了。


我已经从各个方面解决了这个问题,但看不出我做错了什么;还有其他人吗?如果相关,这些是父类中的函数,其中一个函数旨在生成另一个作为线程的函数。


我正在使用的代码:


from datetime import datetime, timedelta

import csv

from drivers.IMU_SEN0 import IMU_SEN0

import multiprocessing, os


class IMU_data_logger:

    _output_filename = ''

    _csv_headers = []

    _accelerometer_headers = ['Accelerometer X','Accelerometer    Y','Accelerometer Z']

    _gyroscope_headers = ['Gyroscope X','Gyroscope Y','Gyroscope Z']

    _magnetometer_headers = ['Bearing']

    _log_accelerometer = False

    _log_gyroscope= False

    _log_magnetometer = False

    IMU = None

    _writer=[]

    _run_underway = False

    _process=[]

    _stop_value = 0


def __init__(self,output_filename='/home/pi/blah.csv',log_accelerometer = True,log_gyroscope= True,log_magnetometer = True):

    """data logging device

    NOTE! Multiple instances of this class should not use the same IMU devices simultaneously!"""        

    self._output_filename = output_filename

    self._log_accelerometer = log_accelerometer

    self._log_gyroscope = log_gyroscope

    self._log_magnetometer = log_magnetometer


def __del__(self):

    # TODO Update this

    if self._run_underway: # If there's still a run underway, end it first

        self.end_recording()


def _set_up(self):        

    self.IMU = IMU_SEN0(self._log_accelerometer,self._log_gyroscope,self._log_magnetometer)

    self._set_up_headers()


答案:对于在这里跟进的任何人,事实证明问题在于我使用了 VS Code 调试器,该调试器显然不适用于多处理,并且以某种方式阻止了生成的进程的成功。


江户川乱折腾
浏览 176回答 1
1回答

叮当猫咪

我可以在您的代码中看到一些错误:首先 stop_value == 0 不会像 multiprocess.Value('i', 0) != 0 那样工作,将该行更改为while stop_value.value == 0其次,你永远不会更新 previous_read_time 所以它会尽可能快地写入读数,你会很快用完磁盘第三,尝试使用 time.sleep() 你正在做的事情被称为忙循环,它很糟糕,它不必要地浪费了 CPU 周期。四,以 self._stop_value = 1 终止可能不会起作用,必须有其他方法来设置该值,也许 self._stop_value.value = 1。好吧,这是基于您提供的代码的示例代码,该代码工作正常:import csvimport multiprocessingimport timefrom datetime import datetime, timedeltafrom random import randintclass IMU(object):    @staticmethod    def read_accelerometer_values():        return dict(x=randint(0, 100), y=randint(0, 100), z=randint(0, 10))class Foo(object):    def __init__(self, output_filename):        self._output_filename = output_filename        self._csv_headers = ['xxxx','y','z']        self._log_accelerometer = True        self.IMU = IMU()    def _record_data(self, frequency, stop_value):        #self._set_up()  # Run setup functions for the data collection device and store it in the self.IMU variable        """Record data function, which takes a recording frequency, in herz, as an input"""        previous_read_time = datetime.now() - timedelta(1, 0, 0)        self._run_underway = True  # Note that a run is now going        Period = 1 / frequency  # Period, in seconds, of a recording based on the input frequency        print("Writing output data to", self._output_filename)        with open(self._output_filename, 'w', newline='') as outcsv:            self._writer = csv.writer(outcsv)            self._writer.writerow(self._csv_headers)  # Write headers to file            while stop_value.value == 0:  # While a run continues                if datetime.now() - previous_read_time >= timedelta(0, 1,                                                                    0):  # If we've waited a period, collect the data; otherwise keep looping                    print("run underway value", self._run_underway)                if datetime.now() - previous_read_time >= timedelta(0, Period,                                                                    0):  # If we've waited a period, collect the data; otherwise keep looping                    next_row = []                    if self._log_accelerometer:                        # Get values in m/s^2                        axes = self.IMU.read_accelerometer_values()                        next_row += [axes['x'], axes['y'], axes['z']]                    previous_read_time = datetime.now()                    self._writer.writerow(next_row)            # Close the csv when done            outcsv.close()    def start_recording(self, frequency_in_hz):        # Create recording process        self._stop_value = multiprocessing.Value('i', 0)        self._process = multiprocessing.Process(target=self._record_data, args=(frequency_in_hz, self._stop_value))        # Start recording process        self._process.start()        print(datetime.now().strftime("%H:%M:%S.%f"), "Data logging process spawned")        print("ID of data logging process: {}".format(self._process.pid))    def end_recording(self, terminate_wait=2):        """Function to end the recording multithread that's been spawned.        Args: terminate_wait: This is the time, in seconds, to wait after attempting to shut down the process before terminating it."""        # Get process id        id = self._process.pid        # Set stop event for process        self._stop_value.value = 1        self._process.join(terminate_wait)  # Wait two seconds for the process to terminate        if self._process.is_alive():  # If it's still alive after waiting            self._process.terminate()            print(datetime.now().strftime("%H:%M:%S.%f"), "Process", id, "needed to be terminated.")        else:            print(datetime.now().strftime("%H:%M:%S.%f"), "Process", id, "successfully ended itself.")if __name__ == '__main__':    foo = Foo('/tmp/foometer.csv')    foo.start_recording(20)    time.sleep(5)    print('Ending recording')    foo.end_recording()
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Python