Как правильно закрыть пару QThread/Process?Python

Программы на Python
Ответить
Anonymous
 Как правильно закрыть пару QThread/Process?

Сообщение Anonymous »

В моей основной программе pyqt5 я создаю экземпляры некоторых классов.
Каждый из этих классов порождает QThread и процесс.
У меня есть проблема с закрытием всех этих пар QThreads/процессов.
Вот что я делаю:
главное событие закрытия:

Код: Выделить всё

    def closeEvent(self,event):
try:
if self.closeEvent_isSet == False:
self.closeEvent_isSet = True

# unsure that record deck is not recording
if self.record_deck_instance.deck_status != "stopped":
self.record_deck_instance.stop_and_close()
event.ignore()
return None

# unsure that ip call is not recording
for i in range(0, 3):
if self.ip_calls_record_deck_instance.ip_calls[i]["deck_status"] == "recording":
self.ip_calls_record_deck_instance.stop_and_close()
event.ignore()
return None

event.ignore()
self.final_slice_instance.put_to_plot = False
self.final_slice_instance.put_to_pyaudio = False
self.final_slice_instance.put_to_record = False
self.deck_1_instance.put_to_q = False
self.deck_2_instance.put_to_q = False
self.music_clip_deck_instance.put_to_q = False

# stop information frame
self.information_frame_instance.close()

# stop deck 1
self.deck_1_instance.close()

# stop deck 2
self.deck_2_instance.close()

# stop speackers deck
self.speackers_deck_instance.close()

# stop music clip deck
self.music_clip_deck_instance.close()

# stop final slice
self.final_slice_instance.close()

# stop final slice plot
self.final_slice_plot_instance.close()

# stop final slice pyaudio
self.final_slice_pyaudio_instance.close()

# stop record deck
self.record_deck_instance.close()

# stop ip call 1
if self.ui.ip_call_1_frame.isVisible():
self.ui.ip_call_1_dismiss.click()
self.ip_call_1_instance.close()

# stop ip call 2
if self.ui.ip_call_2_frame.isVisible():
self.ui.ip_call_2_dismiss.click()
self.ip_call_2_instance.close()

# stop ip call 3
if self.ui.ip_call_3_frame.isVisible():
self.ui.ip_call_3_dismiss.click()
self.ip_call_3_instance.close()

# stop ip calls (aiortc)
self.ip_calls_instance.close()

# stop speackers deck secondary
self.speackers_deck_secondary_instance.close()

# stop secondary slice
self.secondary_slice_instance.close()

# stop secondary slice pyaudio
self.secondary_slice_pyaudio_instance.close()

# ip calls record deck
self.ip_calls_record_deck_instance.close()

# player list
self.player_list_instance.close()

self.close_timer = QtCore.QTimer()
self.close_timer.timeout.connect(lambda: self.MainWindow.close())
self.close_timer.setSingleShot(True)
self.close_timer.start(20)
return None
else:
if all(not item for item in self.processes.values()):
# stop sync processes thread
self.sync_processes_instance.close()

event.accept()
if self.restart:
QtCore.QProcess.startDetached(sys.executable, sys.argv)
else:
try:
self.close_timer.disconnect()
except:
pass
self.close_timer = QtCore.QTimer()
self.close_timer.timeout.connect(lambda:  self.MainWindow.close())
self.close_timer.setSingleShot(True)
self.close_timer.start(20)

event.ignore()
return None
except:
print(traceback.format_exc())
метод закрытия одного экземпляра класса:

Код: Выделить всё

    def close(self):
try:
print("close")
if self.is_closing == False:
self.is_closing = True
self.queue.put({"type":"close"})
print("queue put close...")
else:
try:
self.child_process.terminate()
self.emitter.quit()
except:
pass

while(self.queue.qsize()!=0):
_ = self.queue.get()

manage_processes_class.deinit_process(self)
self.main_self.processes["information_frame_instance_process_state"] = False
except:
self.main_self.processes["information_frame_instance_process_state"] = False
error_message = traceback.format_exc()
#self.main_self.open_information_frame_error_window(error_message)
После первого запуска этого метода close() один элемент закрытия помещается в очередь обработки. Процесс отправляет сообщение о закрытии через эмиттер в QThread, а затем процесс возвращает None. Затем QThread посылает сигнал закрытия экземпляру родительского класса и возвращает None. Наконец, экземпляр родительского класса вызывает close_now() из исходящего сигнала.
метод close_now:

Код: Выделить всё

    def close_now(self):
try:
print("close_now")
self.is_closing = True
self.close()
except:
self.is_closing = True
self.close()
Этот обходной путь, наконец, работает, но что делать, если в QThread возникла ошибка? Тогда сигнал закрытия никогда не будет излучаться, поэтому close_now никогда не будет вызываться, поэтому не будет остановки QThread/Process.
Я хочу использовать современное решение: завершить(), присоединиться () и quit(), чтобы быть максимально простым.
Изменить: я меняю основное closeEvent:

Код: Выделить всё

    def closeEvent(self,event):
try:
self.MainWindow.hide()
# unsure that record deck is not recording
if self.record_deck_instance.deck_status != "stopped":
self.record_deck_instance.stop_and_close()
event.ignore()
return None

# unsure that ip call is not recording
for i in range(0, 3):
if self.ip_calls_record_deck_instance.ip_calls[i]["deck_status"] == "recording":
self.ip_calls_record_deck_instance.stop_and_close()
event.ignore()
return None

self.final_slice_instance.put_to_plot = False
self.final_slice_instance.put_to_pyaudio = False
self.final_slice_instance.put_to_record = False
self.deck_1_instance.put_to_q = False
self.deck_2_instance.put_to_q = False
self.music_clip_deck_instance.put_to_q = False

# stop information frame
self.information_frame_instance.close()

# stop deck 1
self.deck_1_instance.close()

# stop deck 2
self.deck_2_instance.close()

# stop speackers deck
self.speackers_deck_instance.close()

# stop music clip deck
self.music_clip_deck_instance.close()

# stop final slice
self.final_slice_instance.close()

# stop final slice plot
self.final_slice_plot_instance.close()

# stop final slice pyaudio
self.final_slice_pyaudio_instance.close()

# stop record deck
self.record_deck_instance.close()

# stop ip call 1
if self.ui.ip_call_1_frame.isVisible():
self.ui.ip_call_1_dismiss.click()
self.ip_call_1_instance.close()

# stop ip call 2
if self.ui.ip_call_2_frame.isVisible():
self.ui.ip_call_2_dismiss.click()
self.ip_call_2_instance.close()

# stop ip call 3
if self.ui.ip_call_3_frame.isVisible():
self.ui.ip_call_3_dismiss.click()
self.ip_call_3_instance.close()

# stop ip calls (aiortc)
self.ip_calls_instance.close()

# stop speackers deck secondary
self.speackers_deck_secondary_instance.close()

# stop secondary slice
self.secondary_slice_instance.close()

# stop secondary slice pyaudio
self.secondary_slice_pyaudio_instance.close()

# ip calls record deck
self.ip_calls_record_deck_instance.close()

# player list
self.player_list_instance.close()

# stop sync processes thread
self.sync_processes_instance.close()

event.accept()
if self.restart:
QtCore.QProcess.startDetached(sys.executable, sys.argv)
except:
print(traceback.format_exc())
Теперь один метод закрытия:

Код: Выделить всё

    def close(self):
try:
self.queue.put({"type":"close"})
try:
self.child_process.join()
self.child_process.terminate()
self.emitter.quit()
except:
pass

while(self.queue.qsize()!=0):
_ = self.queue.get()

manage_processes_class.deinit_process(self)
except:
error_message = traceback.format_exc()
self.main_self.open_information_frame_error_window(error_message)
Но для принятия события требуется 12 секунд... :/


Подробнее здесь: https://stackoverflow.com/questions/792 ... ad-process
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «Python»