python使用multiprocessing库和threading库实现多进程与多线程

一、多进程

1. 进程的创建步骤

  1. 导入进程包

import multiprocessing

  1. 通过进程类创建进程对象sub_process

sub_process = multiprocessing.Process(target=任务名)

参数名 说明
target 执行的目标任务名,这里指函数名(方法名)
name 进程名,一般不用设置
group 进程组,目前只能使用None
  1. 启动进程执行任务

sub_process.start()

"""
1. 导入进程包
import multiprocessing
2. 通过进程类创建进程对象
sub_process = multiprocessing.Process()
3. 启动进程执行任务
sub_process.start()
"""

import multiprocessing
import time


def sing():
    for i in range(3):
        print("sing")
        time.sleep(0.5)


def dance():
    for i in range(3):
        print("dance")
        time.sleep(0.5)


if __name__ == ‘__main__‘:
    # 创建子进程sing
    sing_process = multiprocessing.Process(target=sing)
    # 创建子进程dance
    dance_process = multiprocessing.Process(target=dance)
    # 启动进程
    sing_process.start()
    dance_process.start()

2. 进程执行带有参数的任务

参数名 说明
args 以元组的形式传参
kwargs 以字典的形式传参
if __name__ == ‘__main__‘:
    # args: 元组形式传参
    sing_process = multiprocessing.Process(target=sing, args=(3,))
    # kwargs: 字典形式传参
    dance_process = multiprocessing.Process(target=dance, kwargs={"num": 3})
    sing_process.start()
    dance_process.start()

3. 获取进程编号

  1. 获取当前进程编号 os.getpid()
  2. 获取当前父进程编号 os.getppid()
import os
pid = os.getpid()
print(pid)
import multiprocessing
import time
import os


def sing(num, name):
    print("sing - current process id", os.getpid())
    print("sing - parent‘s process id", os.getppid())
    for i in range(num):
        print(name)
        print("sing...")
        time.sleep(0.5)


def dance(num, name):
    print("dance - current process id", os.getpid())
    print("dance - the parent‘s process id", os.getppid())
    for i in range(num):
        print(name)
        print("dance...")
        time.sleep(0.5)


if __name__ == ‘__main__‘:
    sing_process = multiprocessing.Process(target=sing, args=(3, "mateo"))
    dance_process = multiprocessing.Process(target=dance, kwargs={"num": 3, "name": "*"})
    sing_process.start()
    dance_process.start()

4. 进程的注意点

  1. 主进程默认会等待所有的子进程执行结束再结束
  2. 设置守护主进程,主进程结束则子进程强制结束 sub_process.daemon = True

5. 进程状态

  1. 判断进程是否正在运行:p.is_alive()
  2. 等待进程结束:p.join()

6. 案例-视频文件夹高并发copy器(多进程)

import multiprocessing
import os
import time


def copy_file(filename, source_dir, destination_dir):
    # 1. 拼接源文件路径和目标文件路径
    source_path = source_dir + "/" + filename
    destination_path = destination_dir + "/" + filename
    # 2. 打开源文件和目标文件
    with open(source_path, "rb") as source_file:
        with open(destination_path, "wb") as destination_file:
            # 3. 循环读取源文件到目标路径
            while True:
                data = source_file.read(1024)
                if data:
                    destination_file.write(data)
                else:
                    break


if __name__ == ‘__main__‘:
    # 1. 定义源文件夹和目标文件夹
    source_dir = r"D:\python\cs61a\resources\tutorials video"
    destination_dir = "videos"
    # 2. 创建目标文件夹
    try:
        os.mkdir(destination_dir)
    except OSError:
        print("folder exists")

    # 3. 读取源文件夹的文件列表
    file_list = os.listdir(source_dir)

    # 开始时间
    start_time = time.perf_counter()
    # 4. 遍历文件列表实现拷贝
    sub_processes = []
    for filename in file_list:
        # copy_file(filename, source_dir, destination_dir)
        # 5. 使用多进程实现多任务拷贝
        sub_process = multiprocessing.Process(target=copy_file,
                                              args=(filename, source_dir, destination_dir))
        sub_process.start()
        sub_processes.append(sub_process)
    # 结束时间
    for sub_process in sub_processes:
        sub_process.join()
    end_time = time.perf_counter()
    print("并发使用时间:", end_time - start_time)

结果1: 并发使用时间: 1.0547636 s, 单线程使用时间: 1.2491160000000001 s

结果2: 并发使用时间: 0.8891155999999999 s, 单线程使用时间: 1.1450036 s

二、多线程

多线程是python程序中实现多任务的一种方式。

线程是程序执行的最小单位

同属一个进程的多个线程共享进程所拥有的全部资源

1. 线程的创建步骤

  1. 导入线程模块

import threading

  1. 通过线程类创建进程对象sub_process

sub_thread = threading.Thread(target=任务名)

参数名 说明
target 执行的目标任务名,这里指函数名(方法名)
name 线程名,一般不用设置
group 线程组,目前只能使用None
  1. 启动线程执行任务

sub_thread.start()

"""
1. 导入线程模块
import threading
2. 通过线程类创建进程对象sub_process
sub_thread = threading.Thread(target=任务名)
3. 启动线程并执行任务
sub_thread.start()
"""
import time
import threading


def sing():
    for i in range(3):
        print("sing...")
        time.sleep(1)


def dance():
    for i in range(3):
        print("dance...")
        time.sleep(1)


if __name__ == ‘__main__‘:

    sing_thread = threading.Thread(target=sing)
    dance_thread = threading.Thread(target=dance)

    sing_thread.start()
    dance_thread.start()

2. 线程执行带有参数的任务

参数名 说明
args 以元组的形式传参
kwargs 以字典的形式传参
if __name__ == ‘__main__‘:
    # args: 元组形式传参
    sing_thread = threading.Thread(target=sing, args=(3,))
    # kwargs: 字典形式传参
    dance_thread = threading.Thread(target=dance, kwargs={"num": 3})
    sing_thread.start()
    dance_thread.start()

3. 主线程与子线程的结束顺序

  1. 主线程默认会等待所有的子线程执行结束再结束

  2. 设置守护主线程,主线程结束则子线程强制结束

    # 设置守护主进程方式 1
    work_thread = threading.Thread(target=work, daemon=True)
    # 设置守护主进程方式 2
    # work_thread.setDaemon(True)
    

4. 线程间的执行顺序

  1. 线程间执行是无序的,由CPU调度决定
  2. 获取当前的线程信息 threading.current_thread()
import time
import threading


def task():
    time.sleep(1)
    # current_thread 获取当前线程的线程对象
    thread = threading.current_thread()
    print(thread)


if __name__ == ‘__main__‘:
    for i in range(5):
        sub_thread = threading.Thread(target=task)
        sub_thread.start()

python使用multiprocessing库和threading库实现多进程与多线程

5. 进程和线程对比

关系对比

  1. 线程依附在进程中,没有进程就没有线程
  2. 一个进程默认提供一条线程,进程可以创建多个线程

区别对比

  1. 创建进程的资源开销比创建线程开销更大
  2. 进程是操作系统资源分配的基本单位,线程是CPU调度的基本单位
  3. 线程不能独立执行

优缺点对比

  1. 进程可以用多核,但资源开销大
  2. 线程资源开销小,但不能使用多核

6. 案例-视频文件夹高并发copy器(多线程)

import threading
import os
import time


def copy_file(filename, source_dir, destination_dir):
    # 1. 拼接源文件路径和目标文件路径
    source_path = source_dir + "/" + filename
    destination_path = destination_dir + "/" + filename
    # 2. 打开源文件和目标文件
    with open(source_path, "rb") as source_file:
        with open(destination_path, "wb") as destination_file:
            # 3. 循环读取源文件到目标路径
            while True:
                data = source_file.read(1024)
                if data:
                    destination_file.write(data)
                else:
                    break


if __name__ == ‘__main__‘:
    # 1. 定义源文件夹和目标文件夹
    source_dir = r"D:\python\cs61a\resources\tutorials video"
    destination_dir = "videos"
    # 2. 创建目标文件夹
    try:
        os.mkdir(destination_dir)
    except OSError:
        print("folder exists")

    # 3. 读取源文件夹的文件列表
    file_list = os.listdir(source_dir)

    # 开始时间
    start_time = time.perf_counter()
    # 4. 遍历文件列表实现拷贝
    sub_threads = []
    for filename in file_list:
        # copy_file(filename, source_dir, destination_dir)
        # 5. 使用多进程实现多任务拷贝
        sub_thread = threading.Thread(target=copy_file,
                                              args=(filename, source_dir, destination_dir))
        sub_thread.start()
        sub_threads.append(sub_thread)
    # 结束时间
    for sub_thread in sub_threads:
        sub_thread.join()
    end_time = time.perf_counter()
    print("并发使用时间:", end_time - start_time, "s")

结果1: 并发使用时间: 0.6955842 s

结果2: 并发使用时间: 0.5768514 s

主要参考:黑马程序员

python使用multiprocessing库和threading库实现多进程与多线程

上一篇:框架 Spring Boot 技术入门到整合 8-4 整合mybatis-自定义mapper的实现


下一篇:python中基本的数据类型