【问题标题】:os.system and subprocess.run make my multi threaded process freeze until call endsos.system 和 subprocess.run 使我的多线程进程冻结,直到调用结束
【发布时间】:2020-11-23 22:49:37
【问题描述】:

我是 python 新手,遇到了一些问题。

我编写了一个 update_manager 类,它可以通过 Tcp 与用户进行通信,并预先安装不同的组件。

我的 update_manager 类使用 2 个其他类(它们是他的成员)来完成此操作。第一个用于 TCP 通信,第二个用于实际安装。安装类从主线程运行,通过Threading.thread()函数进行通信。

我的 ma​​in 锁是这样的:

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("睡眠 5")

我真的很感激一些穷人,谢谢。

【问题讨论】:

  • 还有一件事,当我尝试将 update_manager 的简单版本编写为一个具有 2 个功能(一个打印内容和一个安装 rpm 文件)的类时,没有队列,也没有 TCP。使用相同的 threading.thread() 它可以工作。

标签: python multithreading subprocess message-queue


【解决方案1】:

问题在于传入队列。

我用过:

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

【讨论】:

    猜你喜欢
    • 2015-04-19
    • 1970-01-01
    • 2014-12-22
    • 1970-01-01
    • 1970-01-01
    • 2015-11-21
    • 2015-08-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多