• Python 脚本死锁问题与解决方案


    在这里插入图片描述

    1. 问题背景

    Python 脚本旨在启动多个线程,每个线程又通过 Popen 启动一个子进程。子进程将从一个数据库中的表格中将 10M 条记录传输到另一个数据库中的不同表格中。这个过程中会涉及大量的数据整理和转换,因为两个数据库具有不同的架构。子进程在执行过程中,如果遇到错误(如错误的记录或重复的主键)或执行成功,都会输出 “Done\n”;如果没有更多记录可供传输,则会输出 “NO DATA\n”。

    脚本 “tableTransfer.py” 意在生成这些子进程,读取它们的输出,并依此输出一些信息,如已完成的更新数量、剩余时间、已经过去的时间,以及每秒的传输数量。

    然而,在运行这个脚本一段时间后,遇到了死锁问题。子进程没有在运行,还有记录需要更新,脚本也没有退出。它只是停在那里,不再输出当前信息,因为没有子进程运行来更新总完成数(这是控制输出更新的内容)。

    2. 解决方案

    2.1 使用队列通信

    为了解决死锁问题,需要使用队列来进行进程间通信。队列是一个先进先出的数据结构,可以将数据从一个进程传输到另一个进程。在脚本中,可以创建一个队列来存储子进程的输出,然后由主进程从队列中读取输出并进行处理。这样,子进程就不会阻塞主进程,也不会发生死锁。

    2.2 使用信号处理

    为了处理 Ctrl+C 中断信号,需要使用信号处理模块。该模块提供了处理不同信号的函数,包括 Ctrl+C 中断信号。在脚本中,可以使用信号处理模块注册一个 Ctrl+C 中断信号处理函数,当用户按下 Ctrl+C 时,该函数将被调用。在处理函数中,可以关闭所有子进程并退出脚本。

    2.3 优化脚本结构

    为了提高脚本的可读性和可维护性,可以对脚本的结构进行优化。例如,可以将脚本划分为不同的函数,每个函数负责一个特定的任务。还可以使用面向对象编程来组织代码,使代码更加模块化和易于复用。

    2.4 代码示例

    import queue
    import threading
    import signal
    import subprocess
    
    # 创建一个队列来存储子进程的输出
    output_queue = queue.Queue()
    
    # 创建一个函数来处理子进程的输出
    def process_output(output):
        # 在这里处理子进程的输出
        # ...
    
    # 创建一个函数来启动一个子进程
    def start_subprocess(command):
        # 启动一个子进程
        process = subprocess.Popen(command, stdout=subprocess.PIPE)
    
        # 将子进程的输出添加到队列中
        for line in iter(process.stdout.readline, b''):
            output_queue.put(line.decode('utf-8'))
    
        # 等待子进程完成
        process.wait()
    
    # 创建一个函数来处理 Ctrl+C 中断信号
    def signal_handler(signal, frame):
        # 关闭所有子进程
        for thread in threads:
            thread.join()
    
        # 退出脚本
        exit()
    
    # 注册 Ctrl+C 中断信号处理函数
    signal.signal(signal.SIGINT, signal_handler)
    
    # 创建一个列表来存储线程
    threads = []
    
    # 启动一定数量的线程来启动子进程
    for i in range(10):
        thread = threading.Thread(target=start_subprocess, args=('python script.py',))
        threads.append(thread)
        thread.start()
    
    # 从队列中读取输出并进行处理
    while True:
        output = output_queue.get()
        process_output(output)
    
  • 相关阅读:
    软件设计师--其他高频考点总结
    SAP MM的基础
    Linux MYSQL-5.7.23-rpm安装(附带安装包)
    KT148A语音芯片驱动8欧0.5W的喇叭声音小可以换喇叭或者外挂功放吗
    MySQL常用运算符详细介绍
    【32-业务开发-基础业务-规格参数-保存数据-查询数据-更新操作之数据回显展示-更新操作-前后端项目交互整合与测试-总结收获】
    css3中有哪些伪选择器?
    [附源码]计算机毕业设计springboot酒店客房管理信息系统
    自学Python第二十二天- Django框架(四) iframe、其他组件和工具
    JavaEE >> Spring(2)
  • 原文地址:https://blog.csdn.net/huakej_/article/details/139406788