Python多进程与多线程实战:Process与Thread的使用及守护模式
本文详解Python中多进程与多线程的核心用法。通过Process和Thread类演示任务创建、启动及参数传递(元组与字典),并重点讲解daemon守护模式的两种配置方式。结合代码示例与运行输出,对比分析主进程/线程结束时对子任务的影响,帮助开发者掌握并发编程基础。
进程与线程基础概念
可以将计算机资源比作学校机房:固定数量的电脑对应CPU核心,每台电脑代表一个进程。老师分配爬虫任务,每个学生用一台电脑爬取部分数据并存入公共数据库,这里公共数据库即共享资源。若一台电脑开启多个爬虫实例,则相当于一个进程内包含多个线程,线程数量受限于该电脑的运行内存。总结而言,单个CPU可运行多个进程,而每个进程内部可包含一个或多个线程。
多进程编程实现
第一步:导入所需模块
from multiprocessing import Process
第二步:定义两个独立的任务函数
第三步:实例化进程对象。语法为:进程变量名 = Process(target=函数名, args=参数元组或kwargs=参数字典, daemon=是否守护进程)
第四步:调用进程变量的start()方法以启动进程。
第五步:配置守护进程行为。默认情况下,主进程会等待所有子进程执行完毕后才退出。若希望主进程结束后立即销毁未完成的子进程并关闭程序,可通过两种方式设置守护模式:1. 在创建Process时传入参数daemon=True;2. 在进程对象创建后,设置属性进程变量名.daemon=True。
第六步:获取当前进程ID。需导入os模块,使用os.getpid()获取当前进程编号。
os.getpid()
获取当前父进程ID,使用os.getppid()函数。
os.getppid()
代码示例:未开启进程守护模式
from multiprocessing import Process
import time
import os
# 一个写作业函数
def homeWork(name, count):
for i in range(count):
# 打印当前进程编号os.getpid()
print("当前进程编号:", os.getpid())
# 打印当前父进程编号os.getppid()
print("当前父进程编号:", os.getppid())
print(name, "正在写作业...")
time.sleep(0.2)
# 一个打游戏函数
def game(name, count):
for i in range(count):
# 打印当前进程编号os.getpid()
print("当前进程编号:", os.getpid())
# 打印当前父进程编号os.getppid()
print("当前父进程编号:", os.getppid())
print(name, "正在打游戏...")
time.sleep(0.2)
if __name__ == '__main__':
# 打印当前进程编号os.getpid()
print("当前进程编号:", os.getpid())
# 进程1写作业 元组传参
p1 = Process(target=homeWork, args=("进程1", 10))
# 进程2打游戏 字典传参
p2 = Process(target=game, kwargs={"name": "进程2", "count": 10})
# 启动进程
p1.start()
p2.start()
time.sleep(1)
print("主进程结束---------------------------------------------")
未开启守护模式的运行结果分析
# 观察输出可见,主进程结束后,其子进程仍在继续执行。 当前进程编号: 14972 当前进程编号: 5732 当前父进程编号: 14972 进程1 正在写作业... 当前进程编号: 14752 当前父进程编号: 14972 进程2 正在打游戏... 当前进程编号: 5732 当前父进程编号: 14972 进程1 正在写作业... 当前进程编号: 14752 当前父进程编号: 14972 进程2 正在打游戏... 当前进程编号: 5732 当前父进程编号: 14972 进程1 正在写作业... 当前进程编号: 14752 当前父进程编号: 14972 进程2 正在打游戏... 当前进程编号: 5732 当前父进程编号: 14972 进程1 正在写作业... 当前进程编号: 14752 当前父进程编号: 14972 进程2 正在打游戏... 主进程结束--------------------------------------------- 当前进程编号: 5732 当前父进程编号: 14972 进程1 正在写作业... 当前进程编号: 14752 当前父进程编号: 14972 进程2 正在打游戏... 当前进程编号: 5732 当前父进程编号: 14972 进程1 正在写作业... 当前进程编号: 14752 当前父进程编号: 14972 进程2 正在打游戏... 当前进程编号: 5732 当前父进程编号: 14972 进程1 正在写作业... 当前进程编号: 14752 当前父进程编号: 14972 进程2 正在打游戏... 当前进程编号: 5732 当前父进程编号: 14972 进程1 正在写作业... 当前进程编号: 14752 当前父进程编号: 14972 进程2 正在打游戏... 当前进程编号: 5732 当前父进程编号: 14972 进程1 正在写作业... 当前进程编号: 14752 当前父进程编号: 14972 进程2 正在打游戏...
Process finished with exit code 0
代码示例:开启进程守护模式
from multiprocessing import Process
import time
import os
# 一个写作业函数
def homeWork(name, count):
for i in range(count):
# 打印当前进程编号os.getpid()
print("当前进程编号:", os.getpid())
# 打印当前父进程编号os.getppid()
print("当前父进程编号:", os.getppid())
print(name, "正在写作业...")
time.sleep(0.2)
# 一个打游戏函数
def game(name, count):
for i in range(count):
# 打印当前进程编号os.getpid()
print("当前进程编号:", os.getpid())
# 打印当前父进程编号os.getppid()
print("当前父进程编号:", os.getppid())
print(name, "正在打游戏...")
time.sleep(0.2)
if __name__ == '__main__':
# 打印当前进程编号os.getpid()
print("当前进程编号:", os.getpid())
# 进程1写作业 元组传参 第一种方法启动进程守护
p1 = Process(target=homeWork, args=("进程1", 10), daemon=True)
# 进程2打游戏 字典传参
p2 = Process(target=game, kwargs={"name": "进程2", "count": 10})
# 第二种
p2.daemon = True
# 启动进程
p1.start()
p2.start()
time.sleep(1)
print("主进程---------------------------------------------")
开启守护模式的运行结果分析
当前进程编号: 372 当前进程编号: 10116 当前进程编号: 9860 当前父进程编号: 372 进程1 正在写作业... 当前父进程编号: 372 进程2 正在打游戏... 当前进程编号: 9860 当前进程编号: 10116 当前父进程编号: 372 进程2 正在打游戏... 当前父进程编号: 372 进程1 正在写作业... 当前进程编号: 9860 当前进程编号: 10116 当前父进程编号: 372 进程1 正在写作业... 当前父进程编号: 372 进程2 正在打游戏... 当前进程编号: 9860 当前进程编号: 10116 当前父进程编号: 372 进程1 正在写作业... 当前父进程编号: 372 进程2 正在打游戏... 主进程结束---------------------------------------------
Process finished with exit code 0
多线程编程实现
第一步:导入threading模块
import threading
第二步:定义两个独立的任务函数
第三步:实例化线程对象。语法为:线程变量名 = threading.Thread(target=函数名, args=参数元组或kwargs=参数字典, daemon=是否守护进程)
第四步:调用线程变量的start()方法以启动线程。
第五步:配置守护线程行为。默认情况下,主程序会等待所有子线程执行完毕后才退出。若希望主程序结束后立即销毁未完成的子线程并关闭程序,可通过两种方式设置守护模式:1. 在创建Thread时传入参数daemon=True;2. 在线程对象创建后,设置属性线程变量名.daemon=True。
第六步:获取当前线程对象。使用threading.current_thread()获取当前线程编号或对象信息。
threading.current_thread()
代码示例:未开启线程守护模式
import threading
import time
# 一个写作业函数
def homeWork(name, count):
for i in range(count):
# 打印当前线程
print(threading.current_thread())
print(name, "正在写作业...")
time.sleep(0.2)
# 一个打游戏函数
def game(name, count):
for i in range(count):
# 打印当前线程
print(threading.current_thread())
print(name, "正在打游戏...")
time.sleep(0.2)
if __name__ == '__main__':
# 线程1写作业 元组传参
t1 = threading.Thread(target=homeWork, args=("进程1", 10))
# 线程2打游戏 字典传参
t2 = threading.Thread(target=game, kwargs={"name": "进程2", "count": 10})
# 启动进程
t1.start()
t2.start()
time.sleep(1)
print("主进程结束###################################################################################")
未开启守护模式的运行结果分析
# 观察输出可见,主进程结束后,其线程仍在继续执行。 <Thread(Thread-1, started 3364)> 进程1 正在写作业... <Thread(Thread-2, started 9100)> 进程2 正在打游戏... <Thread(Thread-2, started 9100)> 进程2 正在打游戏... <Thread(Thread-1, started 3364)> 进程1 正在写作业... <Thread(Thread-1, started 3364)> 进程1 正在写作业... <Thread(Thread-2, started 9100)> 进程2 正在打游戏... <Thread(Thread-2, started 9100)> 进程2 正在打游戏... <Thread(Thread-1, started 3364)> 进程1 正在写作业... <Thread(Thread-1, started 3364)> 进程1 正在写作业... <Thread(Thread-2, started 9100)> 进程2 正在打游戏... 主进程结束################################################################################### <Thread(Thread-2, started 9100)> 进程2 正在打游戏... <Thread(Thread-1, started 3364)> 进程1 正在写作业... <Thread(Thread-1, started 3364)> <Thread(Thread-2, started 9100)> 进程2 正在打游戏...进程1 正在写作业... <Thread(Thread-1, started 3364)> 进程1 正在写作业... <Thread(Thread-2, started 9100)> 进程2 正在打游戏... <Thread(Thread-2, started 9100)><Thread(Thread-1, started 3364)> 进程1 进程2正在写作业... 正在打游戏... <Thread(Thread-2, started 9100)><Thread(Thread-1, started 3364)>
进程2 进程1 正在打游戏... 正在写作业...
Process finished with exit code 0
代码示例:开启线程守护模式
import threading
import time
# 一个写作业函数
def homeWork(name, count):
for i in range(count):
# 打印当前线程
print(threading.current_thread())
print(name, "正在写作业...")
time.sleep(0.2)
# 一个打游戏函数
def game(name, count):
for i in range(count):
# 打印当前线程
print(threading.current_thread())
print(name, "正在打游戏...")
time.sleep(0.2)
if __name__ == '__main__':
# 线程1写作业 元组传参
t1 = threading.Thread(target=homeWork, args=("进程1", 10), daemon=True)
# 线程2打游戏 字典传参
t2 = threading.Thread(target=game, kwargs={"name": "进程2", "count": 10})
t2.daemon = True
# 启动进程
t1.start()
t2.start()
time.sleep(1)
print("主进程结束###################################################################################")
开启守护模式的运行结果分析
<Thread(Thread-1, started daemon 15480)> 进程1 正在写作业... <Thread(Thread-2, started daemon 13700)> 进程2 正在打游戏... <Thread(Thread-2, started daemon 13700)> 进程2 正在打游戏... <Thread(Thread-1, started daemon 15480)> 进程1 正在写作业... <Thread(Thread-1, started daemon 15480)><Thread(Thread-2, started daemon 13700)> 进程1 进程2 正在写作业...正在打游戏...
<Thread(Thread-2, started daemon 13700)><Thread(Thread-1, started daemon 15480)>
进程1进程2 正在写作业... 正在打游戏...
<Thread(Thread-1, started daemon 15480)> 进程1 正在写作业... <Thread(Thread-2, started daemon 13700)> 进程2 正在打游戏... 主进程结束###################################################################################
Process finished with exit code 0
本文介绍了Python中多进程与多线程的基本使用方法。如需了解更多Python多进程与多线程相关内容,建议查阅本站过往文章或继续浏览后续教程。感谢大家的支持!
本站声明
本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。













