进程概念
一个正在运行的程序or软件就是一个进程,进程是操作系统进行资源分配的基本单位
启动一个进程操作系统就会分配一定的运行资源保证进程的运行
一个程序的运行至少有一个进程,一个进程默认有一个线程
进程里可以创建多个线程,线程依附于进程存在
import multiprocessing
import time
def task1():
for i in range(8):
print('AAA ', i)
time.sleep(1)
# 编写任务函数
def task2():
for i in range(8):
print('BBB ', i+1)
time.sleep(1)
if __name__ == '__main__':
# 创建子进程对象
# 正常情况下先执行task1 在执行task2
# pro1 = multiprocessing.Process(target=task1())
# pro2 = multiprocessing.Process(target=task2())
pro1 = multiprocessing.Process(target=task1)
pro2 = multiprocessing.Process(target=task2)
# 启动子进程 异步执行
pro1.start()
pro2.start()
以上代码共产生了三个进程,一个主进程和两个子进程
进程编号
获取进程编号的目的是验证主进程与子进程的关系,可以知道子进程是由哪个主进程创建出来的。
获取方法:
1. 获取当前进程编号
os.getpid()
2. 获取当前父进程编号
os.getppid()
3. 获取当前进程对象
mp = multiprocessing.current_process()
举个栗子
import multiprocessing
import time
import os
def task1():
print(f'pid of task1 :{os.getpid()}' f'ppid of task1 :{os.getppid()}')
time.sleep(1)
def task2():
print(f'pid of task2 :{os.getpid()}', f'ppid of task2 :{os.getppid()}')
time.sleep(1)
mp2 = multiprocessing.current_process()
print(mp2)
print(mp2.name)
# 创建子进程
if __name__=='__main__':
mp1 = multiprocessing.current_process()
print(mp1)
print(f'pid of mainprocess :{os.getpid()}', f'ppid :{os.getppid()}')
p1 = multiprocessing.Process(target=task1, name='test1')
p2 = multiprocessing.Process(target=task2, name='test2')
# 启动子进程
p1.start()
p2.start()
<_MainProcess(MainProcess, started)>
pid of mainprocess :14024 ppid :11208
pid of task1 :15328ppid of task1 :14024
pid of task2 :13872 ppid of task2 :14024
<Process(test2, started)>
test2
进程执行带有参数的任务
Process类执行任务并给任务传参有两种方式
1. args 以元组方式传参 【通过元组传一个参数记得添加逗号】
2. kwargs 以字典方式传参
import multiprocessing
import time
def task1(count):
for i in range(count):
print('task--', i+1)
time.sleep(0.5)
def task2(count, content):
for i in range(count):
print(content, '--', i+1)
time.sleep(0.5)
if __name__ == '__main__':
# args传参
# p1 = multiprocessing.Process(target=task1, args=(5,))
# p1.start()
# p2 = multiprocessing.Process(target=task2, args=(5, 'hi'))
# p2.start()
p1 = multiprocessing.Process(target=task1, kwargs={'count':5})
p2 = multiprocessing.Process(target=task2, kwargs={'content':'hello','count':3})
p1.start()
p2.start()
task-- 1
hello -- 1
task-- 2
hello -- 2
task-- 3
hello -- 3
task-- 4
task-- 5
进程之间不共享全局变量
进程创建时复制父进程的进程环境,进程之间相互独立,子进程改变的是复制来的主进程的全局变量的值
import multiprocessing
import time
c_list = []
def add_date():
for i in range(3):
c_list.append(i)
print('add:', c_list, id(c_list))
time.sleep(0.2)
def get_date():
print('get_date:', c_list, id(c_list))
if __name__ == '__main__':
p1 = multiprocessing.Process(target=add_date)
p1.start()
p2 = multiprocessing.Process(target=get_date)
p2.start()
print('main:', c_list, id(c_list))
main: [] 1585715864776
add: [0] 2810619778760
get_date: [] 2304709908168
add: [0, 1] 2810619778760
add: [0, 1, 2] 2810619778760
注意在这里犯了一个错,由于自动补全,导致print结果一致,访问到同一地址
p1 = multiprocessing.Process(target=add_date())
p2 = multiprocessing.Process(target=get_date())
进程执行顺序
主进程会先开始,会等待子进程结束后结束
子进程的执行顺序不一定,可以通过join指定子进程执行顺序
p1.join()
# 等p1执行完
add: [0] 2157796153032
add: [0, 1] 2157796153032
add: [0, 1, 2] 2157796153032
main: [] 2790474388680
get_date: [] 1629914552008
设置守护进程
让子进程在主进程结束后结束
1. 在主进程结束前调用方法结束子进程
p.terminnate()
2. 设置守护进程
设置守护进程时,必须在进程开始前设置
使主进程结束时,子进程也跟着结束
p.daemon = True