问题现象
python代码中有多进程逻辑,或使用Manager用于进程间数据共享。
run过程中,linux下执行’ps -ef’查看相关进程数,有1个主进程18517,4个子进程18523\18528\18533\18535:
18517 17548 0 14:39 ? 00:00:00 /home/anaconda3/envs/python2.7/bin/python /home/Projects/script/main
18523 18517 0 14:39 ? 00:00:00 /home/anaconda3/envs/python2.7/bin/python /home/Projects/script/main
18528 18517 0 14:39 ? 00:00:00 /home/anaconda3/envs/python2.7/bin/python /home/Projects/script/main
18533 18517 0 14:39 ? 00:00:01 /home/anaconda3/envs/python2.7/bin/python /home/Projects/script/main
18535 18517 0 14:39 ? 00:00:00 /home/anaconda3/envs/python2.7/bin/python /home/Projects/script/main
main已执行完毕,执行’ps -ef’可以看到,仍有部分子进程(18523\18528)未销毁,并且主进程号已发生变化:
18523 3058 0 14:39 ? 00:00:00 /home/anaconda3/envs/python2.7/bin/python /home/Projects/script/main
18528 3058 0 14:39 ? 00:00:00 /home/anaconda3/envs/python2.7/bin/python /home/Projects/script/main
解决方案
查看main.py中退出方式,为os._exit(),而不是sys.exit()。
我们来看一下这两者的区别:
- os._exit(n)会直接将python程序终止,之后的所有代码都不会继续执行。以状态码 n 退出进程,不会调用清理处理程序,不会刷新 stdio,等等。
- sys.exit([arg])会引发一个异常:SystemExit,如果这个异常没有被捕获,那么python解释器将会退出。如果有捕获此异常的代码,那么这些代码还是会执行。捕获这个异常可以做一些额外的清理工作。可选参数 arg 可以是表示退出状态的整数(默认为 0),也可以是其他类型的对象。如果它是整数,则 shell 等将 0 视为“成功终止”,非零值视为“异常终止”。大多数系统要求该值的范围是 0–127,否则会产生不确定的结果。
fix方法:将退出方式改为sys.exit()即可
关于Manager类简单介绍
Manager这个对象可以用于在不同进程中共享数据。返回的管理器对象对应了一个已经启动的子进程。multiprocessing.Manager() 创建SyncManager对象,
它拥有一系列方法,可以为大部分常用数据类型创建并返回代理对象代理,用于进程间同步。甚至包括共享列表和字典。
def Manager():
'''
Returns a manager associated with a running server process
The managers methods such as `Lock()`, `Condition()` and `Queue()`
can be used to create shared objects.
'''
from multiprocessing.managers import SyncManager
m = SyncManager()
m.start()
return m
具体可查看:pythono官方文档----管理器
管理器提供了一种创建共享数据的方法,从而可以在不同进程中共享,甚至可以通过网络跨机器共享数据。管理器维护一个用于管理 共享对象 的服务。其他进程可以通过代理访问这些共享对象。