c语言编程笔录

首页 >   > 笔记大全

笔记大全

如何在Python中优雅地结束主进程

更新时间:2023-10-14

第一段:理解Python的进程

在深入探讨如何优雅结束进程之前,我们需要先理解Python中的进程是如何工作的。Python中的进程是程序在运行时的实例,一个程序可以有多个进程,每个进程都在独立的空间中运行,它们可以通过进程间通信机制传递信息。


 # 导入进程模块
import multiprocessing 
import time

def job():
    for i in range(5):
        print('Job:', i, 'pid:', multiprocessing.current_process().pid)
    time.sleep(1)
    print('The end')

if __name__ == '__main__':
    print('Main process PID:', multiprocessing.current_process().pid)
    p1 = multiprocessing.Process(target=job)
    p1.start()
    p1.join()
    print('All done')

在上面的代码示例中,我们导入了 Python 的 multiprocessing 包,并定义了 job() 函数。我们使用 multiprocessing.Process() 函数创建一个新进程并运行 job() 函数。在主进程中,我们使用 p1.join() 语句等待子进程结束。当子进程结束时,在主进程中调用 print('All done!') 函数。

第二段:如何优雅地结束进程

一个进程可以有多种方式结束,比如:自己结束、被其他进程终止或者出现运行时错误等。但是,如果没有特别的要求,建议使用优雅的方式结束进程。所谓优雅的方式就是指在不破坏程序的完整性的前提下,让进程完成清理操作(如关闭文件、删除临时文件、释放占用的资源等)后自行退出。


import multiprocessing 
import time

def job():
    for i in range(5):
        print('Job:', i, 'PID:', multiprocessing.current_process().pid)
    time.sleep(1)

if __name__ == '__main__':
    print('Main Process PID:', multiprocessing.current_process().pid)
    p1 = multiprocessing.Process(target=job)
    p1.start()
    time.sleep(3)
    p1.terminate() # 强制终止进程
    p1.join() # 如果要执行完 job() 函数再结束进程,请注释掉此行
    print('All done')

在上面的代码示例中,我们使用了 p1.terminate() 函数使进程终止。这种方式虽然可以强制终止子进程,但是无法保证子进程能够正常清理资源。因此,我们建议在结束进程时使用 join() 函数。如果要等待子进程执行完 job() 函数后结束进程,只需将 p1.join() 取消注释即可。

第三段:异常处理和信号处理

在 Python 中,我们可以使用异常处理机制或信号处理机制来结束进程。如果进程出现了无法处理的异常,就可以使用异常处理机制结束进程;如果进程正在执行某些操作,但是需要结束进程,就可以使用信号处理机制。


import multiprocessing 
import time 
import signal 
import sys

def job():
    for i in range(5):
        print('Job:', i, 'PID:', multiprocessing.current_process().pid)
    time.sleep(1)

def signal_handler(signal, frame):
    print('\nExiting gracefully')
    sys.exit(0)

if __name__ == '__main__':
    print('Main process PID:', multiprocessing.current_process().pid)
    p1 = multiprocessing.Process(target=job)
    p1.start()
    signal.signal(signal.SIGINT, signal_handler) # 设置信号处理函数
    p1.join()
    print('All done')

在上面的代码示例中,我们定义了一个信号处理函数 signal_handler ,当信号(SIGINT)被触发时,程序就会调用这个信号处理函数来结束进程。我们使用 signal.signal() 函数来设置信号处理函数。

第四段:使用进程池管理进程和任务

虽然 Python 提供了 multiprocessing 包来处理进程,但是如果需要管理一个大规模的进程池,就需要使用更成熟的进程池管理包。Python中的 multiprocessing.pool 包提供了一个 Pool 类来管理进程池和任务分配。


import multiprocessing 
import time 

def job(x):
    return x * x 

if __name__ == '__main__':
    print('Main process PID:', multiprocessing.current_process().pid)
    p = multiprocessing.Pool()
    result = p.map(job, range(1,11))
    print(result)
    p.close()
    p.join()
    print('All done')

在上面的代码示例中,我们创建了一个进程池对象 p, 然后使用 map() 函数向进程池中分配任务。在分配任务后,我们使用 close() 函数关闭进程池,最后使用 join() 函数等待子进程完全结束。如果需要优雅地结束进程池,可以在调用 close() 函数后再调用 terminate() 函数。