Python多进程

本文最后更新于 2026年8月22日

未完待续

进程是操作系统进行资源分配的基本单位,每个进程拥有一块独立的内存空间,可以通过python os模块的方法来获取当前运行python程序的所属进程号和父进程号,在任务管理器中,通过进程号能查找到对应进程

import os

print(os.getpid())
print(os.getppid())
27516
13228

在Pycharm IDE中启动python解释器时,父进程往往就是Pycharm IDE


1.创建进程

python使用multiprocessing.Process类来管理进程,创建进程时就要通过target制定好进程将要执行的任务,创建后,调用start()方法,向操作系统申请进程,将该进程交给操作系统进行调度,子进程才会真的启动。可以使用multiprocessing.current_process()方法获取当前进程

创建进程的Process(target=study)必须出现在 if __name__ == '__main__':内,因为当新进程创建时,python底层会启动一个新的解释器,再次运行study函数所在py文件,只获得study函数的定义交给子进程,如果没有 if __name__ == '__main__':判断,Process(target=study)也会被新的解释器进程执行到,最终出现死循环创建进程

当子进程的解释器运行py文件时,__name__也是有值的,它的值是:__mp_main__

执行时,主/子进程执行是异步的,子进程执行不影响主进程

子进程之间也不一定是先start()的先执行,一切以操作系统调度为准

import os
import time
from multiprocessing import Process, current_process

print('hello world ', __name__)

def study():
    for i in range(100):
        print('%s %s 父进程 %s 进程 %s Study' % (current_process(), i, os.getppid(), os.getpid()) , end='\n')
        time.sleep(1)

def speak():
    for i in range(100):
        print('%s %s 父进程  %s 进程 %s speak' % (current_process(), i, os.getppid(), os.getpid()) , end='\n')
        time.sleep(1)



if __name__ == '__main__':
    print('主进程开始执行')
    print('主进程 ', os.getpid())

    p1 = Process(target=study)
    p2 = Process(target=speak)

    p1.start()
    p2.start()
    print('主进程结束执行')

hello world  __main__
主进程开始执行
主进程  12080
主进程结束执行
hello world  __mp_main__
<Process name='Process-3' parent=12080 started> 0 父进程 12080 进程 45936 Study
hello world  __mp_main__
<Process name='Process-4' parent=12080 started> 0 父进程  12080 进程 44440 speak
<Process name='Process-3' parent=12080 started> 1 父进程 12080 进程 45936 Study
<Process name='Process-4' parent=12080 started> 1 父进程  12080 进程 44440 speak
<Process name='Process-3' parent=12080 started> 2 父进程 12080 进程 45936 Study
<Process name='Process-4' parent=12080 started> 2 父进程  12080 进程 44440 speak
<Process name='Process-3' parent=12080 started> 3 父进程 12080 进程 45936 Study
<Process name='Process-4' parent=12080 started> 3 父进程  12080 进程 44440 speak
<Process name='Process-3' parent=12080 started> 4 父进程 12080 进程 45936 Study
<Process name='Process-4' parent=12080 started> 4 父进程  12080 进程 44440 speak
<Process name='Process-3' parent=12080 started> 5 父进程 12080 进程 45936 Study
<Process name='Process-4' parent=12080 started> 5 父进程  12080 进程 44440 speak
.............

Process类有以下参数,有的是继承来的:

  • group 默认为None
  • target 子进程要运行的可执行对象,默认为None
  • name 进程名,默认None,系统自动分配名字
  • args 为目标target传递的位置可变(元组)参数
  • kwargs 为目标target传递的关键字可变(字典)参数
  • daemon 布尔值,是否为守护进程,默认为None意思是从父进程继承

2.进程锁

python多进程打印会出现抢占现象,例如本程序打印时,有的打印会出现一行超过4个字符,不到4个字符或数字字母字符混在一行的情况,在python中,打印语句执行时,会先打印内容,再打印end=,如果一个进程打印完内容还没有打印end=,控制台就被另一进程抢走打印其他进程的内容,就会出现这个现象。

from multiprocessing import Process, current_process

def study():
    for i in range(800):
        print('a', end='')
        print('b', end='')
        print('c', end='')
        print('d', end='\n')

def speak():
    for i in range(800):
        print('1', end='')
        print('2', end='')
        print('3', end='')
        print('4', end='\n')

def fun():
    for i in range(800):
        print('@', end='')
        print('!', end='')
        print('$', end='')
        print('%', end='\n')

if __name__ == '__main__':
    task1 = Process(target=study)
    task2 = Process(target=speak)
    task3 = Process(target=fun)

    task3.start()
    task1.start()
    task2.start()
........
abcd
1abcd
23abc4d

a1b2c3d4

a1b234cd
a
b123c4
123d4
12
abcd3
abc4d
........

python采用进程锁Lock/RLock来解决这个问题,lock.acquire()获取锁即获得执行权,其他线程进入等待,没获取到则一直等待直到获取锁,执行完成后lock.release()释放锁

python中acquire/release构成一个原子操作,也必须成对出现,否则会导致锁被一个进程一直持有程序中断

acquire/release可以配合上下文管理with来使用,效果相同更加简洁,异常了也能自动释放锁

from multiprocessing import Process, Lock

def study(lock):
    for i in range(800):
        try:
            lock.acquire()
            print('a', end='')
            print('b', end='')
            print('c', end='')
            print('d')
        finally:
            lock.release()
        
def speak(lock):
    for i in range(800):
        with lock:
            print('1', end='')
            print('2', end='')
            print('3', end='')
            print('4')

def fun(lock):
    for i in range(800):
        with lock:
            print('@', end='')
            print('!', end='')
            print('$', end='')
            print('%')

if __name__ == '__main__':
    lock = Lock()

    task1 = Process(target=study, args=(lock,))
    task2 = Process(target=speak, args=(lock,))
    task3 = Process(target=fun, args=(lock,))

    task3.start()
    task1.start()
    task2.start()

❗Lock锁不可重复,重复加锁会导致第二次加锁时进入无限等待锁释放,造成死锁,比如一个加了Lock或with lock结构的函数中调用了同样有Lock或with lock结构的另一函数

解决这个问题,实际开发中常用支持计数的multiprocessing.RLock锁,用法相同

3.进程常见方法

3.1 join

join()方法,会阻塞当前调用join()方法的进程,等join前的进程执行完,再继续往下执行

a() {
    //a方法在此处被阻塞了,而不是b被阻塞
    b.join()
}

只有已经start()的进程,才能join()

例:p1.join()导致主进程阻塞,p1执行后,p2才启动,p2.join()再次导致主进程阻塞,p2执行,然后主进程执行,两个子进程先后执行


if __name__ == '__main__':
    print('主进程开始执行')
    print('主进程 ', os.getpid())

    p1 = Process(target=study)
    p2 = Process(target=speak)

    p1.start()
    p1.join()

    p2.start()
    p2.join()

    print('主进程结束执行')
主进程开始执行
主进程  19424
<Process name='Process-1' parent=19424 started> 0 父进程 19424 进程 33352 Study
<Process name='Process-1' parent=19424 started> 1 父进程 19424 进程 33352 Study
<Process name='Process-1' parent=19424 started> 2 父进程 19424 进程 33352 Study
<Process name='Process-2' parent=19424 started> 0 父进程  19424 进程 25508 speak
<Process name='Process-2' parent=19424 started> 1 父进程  19424 进程 25508 speak
<Process name='Process-2' parent=19424 started> 2 父进程  19424 进程 25508 speak
主进程结束执行

例:p1p2同时启动后,再同时阻塞主进程,都执行完成后,然后主进程执行,两个子进程会交替执行

import os
import time
from multiprocessing import Process, current_process

def study():
    for i in range(3):
        print('%s %s 父进程 %s 进程 %s Study' % (current_process(), i, os.getppid(), os.getpid()) , end='\n')
        time.sleep(1)

def speak():
    for i in range(3):
        print('%s %s 父进程  %s 进程 %s speak' % (current_process(), i, os.getppid(), os.getpid()) , end='\n')
        time.sleep(1)

if __name__ == '__main__':
    print('主进程开始执行')
    print('主进程 ', os.getpid())

    p1 = Process(target=study)
    p2 = Process(target=speak)

    p1.start()
    p2.start()
    p1.join()
    p2.join()

    print('主进程结束执行')
主进程开始执行
主进程  6568
<Process name='Process-1' parent=6568 started> 0 父进程 6568 进程 4684 Study
<Process name='Process-2' parent=6568 started> 0 父进程  6568 进程 6052 speak
<Process name='Process-1' parent=6568 started> 1 父进程 6568 进程 4684 Study
<Process name='Process-2' parent=6568 started> 1 父进程  6568 进程 6052 speak
<Process name='Process-1' parent=6568 started> 2 父进程 6568 进程 4684 Study
<Process name='Process-2' parent=6568 started> 2 父进程  6568 进程 6052 speak
主进程结束执行

例:p1p2同时启动后,仅p1阻塞主进程,p1p2会同时执行,但是主进程会等p1执行完成后开始执行

import os
import time
from multiprocessing import Process, current_process

def study():
    for i in range(3):
        print('%s %s 父进程 %s 进程 %s Study' % (current_process(), i, os.getppid(), os.getpid()) , end='\n')
        time.sleep(1)

def speak():
    for i in range(5):
        print('%s %s 父进程  %s 进程 %s speak' % (current_process(), i, os.getppid(), os.getpid()) , end='\n')
        time.sleep(3)

if __name__ == '__main__':
    print('主进程开始执行')
    print('主进程 ', os.getpid())

    p1 = Process(target=study)
    p2 = Process(target=speak)

    p1.start()
    p2.start()

    p1.join()

    print('主进程结束执行')
主进程开始执行
主进程  17316
<Process name='Process-1' parent=17316 started> 0 父进程 17316 进程 32520 Study
<Process name='Process-2' parent=17316 started> 0 父进程  17316 进程 15728 speak
<Process name='Process-1' parent=17316 started> 1 父进程 17316 进程 32520 Study
<Process name='Process-1' parent=17316 started> 2 父进程 17316 进程 32520 Study
<Process name='Process-2' parent=17316 started> 1 父进程  17316 进程 15728 speak
主进程结束执行
<Process name='Process-2' parent=17316 started> 2 父进程  17316 进程 15728 speak
<Process name='Process-2' parent=17316 started> 3 父进程  17316 进程 15728 speak
<Process name='Process-2' parent=17316 started> 4 父进程  17316 进程 15728 speak

join方法可以传递一个timeout参数,单位是秒,代表等待多少秒就不等了

例:p1只阻塞主进程3秒,函数执行两秒后打印,第二次进入循环已经是4秒后,此时3秒定时到期,主线程已经执行过

import os
import time
from multiprocessing import Process, current_process


def study():
    for i in range(5):
        time.sleep(2)
        print('%s %s 父进程 %s 进程 %s Study' % (current_process(), i, os.getppid(), os.getpid()) , end='\n')


if __name__ == '__main__':
    print('主进程开始执行')
    print('主进程 ', os.getpid())

    p1 = Process(target=study)
    p1.start()
    p1.join(3)

    print('主进程结束执行')
主进程开始执行
主进程  33136
<Process name='Process-1' parent=33136 started> 0 父进程 33136 进程 26276 Study
主进程结束执行
<Process name='Process-1' parent=33136 started> 1 父进程 33136 进程 26276 Study
<Process name='Process-1' parent=33136 started> 2 父进程 33136 进程 26276 Study
<Process name='Process-1' parent=33136 started> 3 父进程 33136 进程 26276 Study
<Process name='Process-1' parent=33136 started> 4 父进程 33136 进程 26276 Study

3.2 terminate

terminate()用于向操作系统申请终止某个进程,是异步执行的,终止申请发送给操作系统,由操作系统决定什么时机终止,并非立即关闭

执行terminate(),被终止进程运行中方法的finally语句不会执行

import os
import time
from multiprocessing import Process, current_process
from time import sleep

def study():
    for i in range(5):
        print('%s %s 父进程 %s 进程 %s Study' % (current_process(), i, os.getppid(), os.getpid()) , end='\n')
        time.sleep(2)

def speak():
    for i in range(5):
        print('%s %s 父进程  %s 进程 %s speak' % (current_process(), i, os.getppid(), os.getpid()) , end='\n')
        time.sleep(2)

if __name__ == '__main__':
    print('主进程开始执行')
    print('主进程 ', os.getpid())

    p1 = Process(target=study, name='p1')
    p2 = Process(target=speak, name='p2')

    p1.start()
    p2.start()

    sleep(5)
    p1.terminate()
    print(p1.is_alive())

    print('主进程结束执行')
主进程开始执行
主进程  22236
<Process name='p1' parent=22236 started> 0 父进程 22236 进程 31636 Study
<Process name='p2' parent=22236 started> 0 父进程  22236 进程 20860 speak
<Process name='p1' parent=22236 started> 1 父进程 22236 进程 31636 Study
<Process name='p2' parent=22236 started> 1 父进程  22236 进程 20860 speak
<Process name='p1' parent=22236 started> 2 父进程 22236 进程 31636 Study
<Process name='p2' parent=22236 started> 2 父进程  22236 进程 20860 speak
True
主进程结束执行
<Process name='p2' parent=22236 started> 3 父进程  22236 进程 20860 speak
<Process name='p2' parent=22236 started> 4 父进程  22236 进程 20860 speak

如需确认关闭成功再继续,可以终止前join一下

... ...
p1.terminate()
p1.join()
print(p1.is_alive()) # True

4.守护进程

4.进程通信

5.进程池


"如果文章对您有帮助,可以请作者喝杯咖啡吗?"

微信二维码

微信支付

支付宝二维码

支付宝


Python多进程
https://blog.liuzijian.com/post/2026/03/20/python-process/
作者
Liu Zijian
发布于
2026年3月20日
更新于
2026年8月22日
许可协议