Можно ли передать многопроцессорную очередь Python дочернему процессу?
У меня есть большой набор данных в системе сбора данных, которую я написал на python, и для передачи очереди от дочернего процесса к родительскому процессу требуется бесконечно много времени. Я хочу сохранить данные, полученные в конце приобретения, и попробовал это, используя queue
функция в Multiprocessing
, Вместо того, чтобы делать это таким образом, я бы предпочел, чтобы я мог передать сообщение через queue
от родителя к ребенку, чтобы сохранить мои данные, прежде чем я уничтожу дочерний процесс. Это возможно? Пример того, что я думал, может выглядеть так:
def acquireData(self, var1, queue):
import h5py
# Put my acquisition code here
queue.get()
if queue == True:
f = h5py.File("FileName","w")
f.create_dataset('Data',data=data)
f.close()
if __name__ == '__main__':
from multiprocessing import Process, Queue
queue = Queue()
inter_thread = Process(target=acquireData, args=(var1,queue))
queue.put(False)
inter_thread.start()
while True:
if not args.automate:
# Let c++ threads run for given amount of time
# Wait for stop from OP GUI
else:
queue.put(True)
break
print("Acquisition finished, cleaning up...")
sleep(2)
inter_thread.terminate()
Это разрешено? Если этот тип взаимодействия между процессами разрешен, тогда у меня есть правильная запись? Для справки, у меня есть порядка 9e7 точек данных в массиве, которые я пытаюсь сохранить, и у меня есть 7 массивов, которые просто не передаются моему родительскому процессу своевременно, помещая эти массивы в queue
, Спасибо.
1 ответ
Во-первых, да, передача очереди дочернему элементу является не только законной, но и основной сценарием использования для очередей. Смотрите первый пример в документации, которая делает именно это.
Однако у вас есть некоторые проблемы с вашим кодом:
queue.get()
if queue == True:
Во-первых, ваш queue
никогда не будет булево значение True
это будет Queue
, Вы почти никогда не хотите проверять if x == True:
в Python; ты хочешь проверить if x:
, Например, if [1, 2]:
пройдет, пока if [1, 2] == True:
не буду.
Во-вторых, ваш queue
это даже не то, что вы хотите проверить в первую очередь. Это не правда или ложь (или не важно, так ли это); это значение, которое основной процесс ставит в очередь, и вы извлекли из него либо правду, либо ложь. Который вы выбросили, как только вы его получили.
Итак, сделайте это:
flag = queue.get()
if flag:
Или проще:
if queue.get():
Я не уверен, что это именно то, что вы хотите или нет. Тот queue.get()
будет блокироваться навсегда, пока основной процесс не поместит что-то туда. Это то, что вы хотели? Если так, отлично; вы закончили с этой частью вашего кода. Если нет, вам нужно подумать о том, что вы хотели вместо этого.
Как и было задумано, родитель всегда будет ждать 2 секунды, даже если ребенок закончил задолго до этого. Лучшим решением является join
ребенок с тайм-аутом 2 секунды. Тогда ты можешь terminate
это если тайм-аут.
Кроме того, вы уверены, что разработанное вами поведение завершения - то, что вы хотите? Вы выполняете "мягкий запрос на удаление" с очередью, затем ждете 2 секунды, а затем выполняете "средний и жесткий запрос" на terminate
и никогда не совершать "тяжелое убийство" с kill
, Это может быть вполне разумный дизайн, но если это не ваш дизайн, вы реализовали не то, что нужно.