我正在开发一个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()
调用。
__del__
调用不起作用,因为它从未被调用过。此外,我还想避免使用with tape:
上下文语法(可能会同时创建和使用多个磁带)。device.get_latest_data_as_numpy_array()
调用可能需要几秒钟才能返回,因此向MyRecorder添加一个计时器,以检查x秒内是否没有数据并不是真正的解决方案。