当前位置:首页>python>Python快速入门学习笔记二十九:进程(一):核心概念、使用Process创建进程

Python快速入门学习笔记二十九:进程(一):核心概念、使用Process创建进程

  • 2026-10-11 07:35:39
Python快速入门学习笔记二十九:进程(一):核心概念、使用Process创建进程
❝

Python入门第二十九课,开始学习进程与线程,主要是学习了一些相关核心概念,以及介绍如何使用Process创建进程,及其运行原理(重要)。

  • 核心概念
    • 并发 vs 并行
    • 同步 vs 异步
    • 进程 vs 线程
  • 主进程 vs 子进程
  • 使用 Process 创建进程
  • 关于 Process 的参数

核心概念

并发 vs 并行

❏ 并发

在一段时间内,当CPU面对多个任务时,会将每个任务交替着执行一段时间。

特点:

  • 对于某个瞬间,CPU实际上只在执行一个任务。
  • CPU通过高频切换不同的任务,让每个任务都能得到推进,仿佛多个任务在“同时执行”。

❏ 并行

并行依赖于多个CPU,或多核心的CPU,在同一时刻,每个核心都在执行不同的任务。

特点:

  • 对于某个瞬间,每个CPU(或每个核心)都在执行不同的任务。
  • 通过多个CPU(或多个核心)同时工作的方式,让多个任务真的在同时执行。
❝

注意:现代操作系统中,并发与并行通常同时存在。

同步 vs 异步

❏ 同步(sync)

发起一个任务之后,需要等该任务完成后,才能继续执行后续任务。

表现为:当前执行流会被『阻塞』。

❏ 异步(async)

发起一个任务之后,不必等待该任务完成,就可以继续执行其他任务。

虽然不必等待任务完成,但任务完成后,仍然可以通过特定方式获取结果。

表现为:当前的执行流不会被『阻塞』。

❝

以上概念对比总结:

并发/并行:描述的是任务如何被执行,即:多个任务在执行时,CPU 要如何处理。

同步/异步:描述的是任务如何被组织和等待,即:是否等当前任务执行完,再进行下一个任务。

注意点:

CPU的核心数和执行速度,不会改变任务之间的逻辑依赖关系!例如:一旦任务1、任务2、任务3之间被设计为同步关系,那么:即便CPU切换任务的速度再快,核心数量再多,也不会在【任务1】没完成的情况下去启动【任务2】。

进程 vs 线程

❏ 进程

一个正在运行的程序或软件,背后就对应着一个或多个进程。

进程是操作系统进行资源分配的基本单位。

每个进程都有自己独立的一块内存空间。

❏ 线程

线程是进程内部的执行单元(一个进程中可以有多个线程)。

线程是操作系统进行CPU调度的基本单位。

同一进程内的线程共享进程资源。

主进程 vs 子进程

在操作系统中,每个进程都会对应一个进程编号(PID),并且主进程和子进程是一个相对的概念,比如:A进程中创建了B进程,B进程中创建了C进程,那此时的B进程既是A进程的子进程,又是C进程的(主)父进程。

Python 中查看进程 PID 的方式:

  • os.getpid()获取当前进程ID。
  • os.getppid()获取父进程ID。
pid = os.getpid()ppid = os.getppid()print(f'当前进程ID:{pid}')print(f'父进程ID:{ppid}')

Windows 命令查看:进程名、父进程PID、进程PID:

wmic process get Name,ParentProcessId,ProcessId

运行结果:

使用 Process 创建进程

使用multiprocessing.Process类创建进程对象。

import osimport timefrom multiprocessing import Process# 打印这一行是为了证明这个文件被运行了3次print(100, __name__, os.getpid(), current_process().name, '\n')# 定义一个 speak 函数,功能是:每隔一秒说话一次(一共说话10次)defspeak():for index in range(10):        print(f'我在说话{index},进程pid是:{os.getpid()},我的父进程是:{os.getppid()}')        time.sleep(1)# 定义一个 study 函数,功能是:每隔一秒学习一次(一共学习15次)defstudy():for index in range(15):        print(f'我在学习{index},进程pid是:{os.getpid()},我的父进程是:{os.getppid()}')        time.sleep(1)# 注意:一定要写 if __name__ == '__main__' 这个判断,原因如下:#   1、当创建子进程时,Python 并不会把父进程内存里的 speak 函数直接交给子进程。#   2、Python 会启动一个全新的 Python 解释器进程,重新执行当前的 .py 文件(作为模块)。#   3、在执行过程中,重新定义出一个 speak 函数,交给子进程。if __name__ == '__main__':    print('我是主进程中的【第一行】打印', os.getpid())# 创建两个 Process 类的实例对象(进程对象),分别是 p1 和 p2。# 注意点1:p1 和 p2 就对应着以后的两个子进程,在创建它们的时候,就要指定好它们要执行的任务。# 注意点2:此时p1 和 p2 只是代码层面的两个进程对象,操作系统还没有创建 p1 和 p2 两个进程。    p1 = Process(target=speak)    p2 = Process(target=study)# 调用进程对象的 start 方法,会立刻向操作系统申请一个进程,并且会将该进程交由操作系统进行调度。    p1.start()    p2.start()# 实际运行证明 p1.start() 和 p2.start() 是异步的    print('我是主进程中的【最后一行】打印')
❝

注意:在 Windows 中使用multiprocessing必须加上if __name__ == 'main',原因是:创建子进程时,Python 不会直接拷贝内存里的函数给子进程。Python 会启动一个全新的解释器,重新执行当前的.py文件作为模块。如果不加判断,会无限递归创建子进程。

关于 Process 的参数

在实例化Process时,可以传递以下参数:

✧ group默认值为None(应当始终为None)。

✧ target子进程要执行的可调用对象,默认值为None。

✧ name进程名称,默认为None,如果设置为None,Python 会自动分配名字。

✧ args给target传的位置参数(元组)。

✧ kwargs给target传的关键字参数(字典)。

✧ daemon标记进程是否为守护进程,取值为布尔值(默认为None,表示从创建方继承)。

可以使用current_process().name获取当前进程的名字。

defspeak(a, b, msg):for index in range(10):        print(f'我在说话{index},进程pid是:{os.getpid()},我的父进程是:{os.getppid()},{msg} -- {a} -- {b} -- {current_process().name}')        time.sleep(10)defstudy():for index in range(15):        print(f'我在学习{index},进程pid是:{os.getpid()},我的父进程是:{os.getppid()}')        time.sleep(1)if __name__ == '__main__':    print('我是主进程中的【第一行】打印')    p1 = Process(target=speak, name="说话进程", args=(666, 888), kwargs={'msg': '远方的你'})    p2 = Process(target=study)    p1.start()    p2.start()    print('我是主进程中的【最后一行】打印')

最新文章

随机文章