Python'析构函数'在模块中杀死子进程

时间:2015-03-13 11:55:38

标签: python python-2.7 multiprocessing

我正在开发一个Mycodule,它从c库中读取一些(巨大的和实时的)数据并将其写入PyTables。由于需要收集的数据量(甚至300MB / s),PyTables在分离的进程上被访问,数据包被推送通过多处理队列。

class Tape(object):

    def __init___(self):
        self.writeq = multiprocessing.Queue()
        self.killq = multiprocessing.Queue()
        self.recorder = MyRecorder(self.writeq, self.killq)
        self.recorder.start()

    def Record(self, recording):
        if isinstance(recording, numpy.ndarray):
            self.writeq.put(recording)

    def Close(self):
        self.killq.put("time to go")
        self.recorder.join()
        for q in (self.writeq, self.killq):
            q._buffer.clear()
            q.close()
            q.join_thread()

class MyRecorder(multiprocessing.Process):

    def __init__(self, writeq, killq):
        self.writeq = writeq
        self.killq = killq
        self.handle = tables.openFile("/tmp/recoding.h5")
        self.number = 0
        super(MyRecorder, self).__init__()

    def run():
        running = True
        while running:
            record = None
            command = None
            try:
                record = self.writeq.get(block = False)
                if isinstance(record, numpy.ndarray):
                    a = self.handle.createArray("/", "record%08d" % self.number, recording)
                    a._f_close(True)
                    self.number += 1
            except Queue.Empty:
                pass

            try:
                command = self.killq.get(block = False)
                if isinstance(command, basestring) and command == "time to go":
                    running = False
            except Queue.Empty:
                pass

            if record is None and command is None:
                time.sleep(0.001)

        self.handle.flush()
        self.handle.close()

用户将以这种方式使用我的模块:

tape = MyModule.Tape()
device = MyOtherModule.Device()
while True:
    record = device.get_latest_data_as_numpy_array()
    if record is not None:
        tape.Record(record)
    else:
        break

tape.Close()
exit(0)

问题

我想确保如果用户忘记调用tape.Close(),则在调用退出时(或程序以其他方式终止),磁带内的进程仍会终止。必须以这种或那种方式调用tape.Close()调用。

  1. 向Tape类添加__del__调用不起作用,因为它从未被调用过。此外,我还想避免使用with tape:上下文语法(可能会同时创建和使用多个磁带)。
  2. 我已经添加了监视程序线程来处理Tape和Myrecorder之间的心跳 - 但是只有当这些故障中的任何一个崩溃并被异常撕掉时才会有用。
  3. device.get_latest_data_as_numpy_array()调用可能需要几秒钟才能返回,因此向MyRecorder添加一个计时器,以检查x秒内是否没有数据并不是真正的解决方案。

0 个答案:

没有答案