python - os.system 和 subprocess.run 使我的多线程进程冻结,直到调用结束
问题描述
我是 python 新手,遇到了一些问题。
我编写了一个 update_manager 类,它可以通过 Tcp 与用户进行通信并预先安装不同的组件。
我的 update_manager 类使用 2 个其他类(它们是他的成员)来完成此操作。第一个用于 TCP 通信,第二个用于实际安装。安装类从主线程运行,通信使用 Threading.thread() 函数运行。
我的主要锁是这样的:
if __name__ == "__main__":
new_update = UpdateManager()
#time.sleep(10)
new_update.run()
运行功能是:
def run(self):
comm_thread = threading.Thread(target=
self._comm_agent.start_server_tcp_comunication)
comm_thread.start()
while True:
if (False == self.is_recovery_required()):
self.calculate_free_storage_for_update_zip_extraction()
self.start_communication_with_client_in_state_machine()
self._comm_agent.disable_synchronized_communication()
self.start_update_install()
self._comm_agent.enable_synchronized_communication()
if (True == self.is_dry_run_requested()):
self.preform_cleanup_after_dry_run()
else:
self.reset_valid_states()
self.preform_clean_up_after_update_cycle()
我使用 2 multiprocessing.Queue() 在线程之间和用户之间进行同步。一个用于传入消息,一个用于传出消息。
起初 TCP 通信是同步的,用户提供安装文件和其他一些东西。
一旦安装开始,TCP 通信就不再同步。
在安装过程中,我使用了 4 种不同的安装方法。并且除了一个之外的所有工作都没有问题(用户可以汇集 update_manager 进程并询问进度问题并立即得到答复)
有问题的一个是 rpm 文件的实例化。为此,我尝试调用 os.system() 和 subprocess.run() 并且它可以工作,但是对于大 rpm 文件,我注意到整个进程与我的线程冻结,直到调用完成(我可以看到我的 rpm 安装的进度条在此冻结期间的屏幕)。
我注意到并尝试的: 1.在其他使用python的安装方法期间没有冻结。图书馆。
2.一旦用户通过 TCP 连接,update_manager 只有 2 个线程,一旦发送第一个请求并发送回回复,就会出现另外 2 个线程(我假设它与我使用的队列有关)。
3.我创建了第三个打印时间的线程(与队列无关),我在 update_manager 进程启动后立即启动它。当 2 个线程冻结时,这个线程会继续运行。
4.在极少数情况下,进程会解冻,只是为了让消息从客户端发送到 update_manager 并冻结回来。
编辑:我忘记了更重要的一点 5. 调用时发生冻结: os.system("rpm --nodeps --force -ivh rpm_file_name")
但是调用时不会发生: os.system("sleep 5")
我真的很感激一些穷人,谢谢。
解决方案
问题在于传入队列。
我用了:
if (True == self._outgoing_message_queue.empty()):
temp: dict = self._outgoing_message_queue.get()
这是一个简单的错误,线程刚刚卡在一个空队列上。
但是即使将代码更改为
if (False == self._outgoing_message_queue.empty()):
temp: dict = self._outgoing_message_queue.get()
它可能会导致相同的行为,因为在评估 if 语句和调用 get() 的那一刻之间,可能会发生联系开关,并且队列可能会变空并且线程将卡在 .get() 上,就像在我的原始代码中一样.
更好的解决方案是使用 get_nowait()
try:
temp = self._outgoing_message_queue.get_nowait()
except:
temp = None
推荐阅读
- php - 增加星号和零的打印模式
- c++ - 在计算数字总和时,如果分配变量的范围超出,则给出一些数值。该值是什么意思?
- gatsby - Gatsby sourceNode 不适用于 GraphQL 参数
- python - 如何在日期时间类型的对象处修复 Python 不是 JSON 可序列化错误
- c++ - Opengl sws_scale 不工作(分段错误)
- angular - MatSidenav 和 MatDrawer 有什么区别?
- python - “str”对象没有属性“dropna”
- python - Python启动器在mac中根本不起作用
- c# - 邮递员 POST 请求模型绑定不适用于 IFormfile 属性
- javascript - 带有条件的模板上的属性绑定