python多线程编程 入门笔记(上)

python多线程编程(上)


前言

在b站看到的多线程视频,现将笔记分享如下。
下半部分链接


课程介绍

学前须知

需掌握python基础语法、python文件操作、python模块应用

开发工具

pycharm

课程安排

进程实现多任务 线程实现多任务 多任务应用

一、多任务介绍

电脑中的多任务

如下载文件

多任务的优势:
多任务的最大好处是充分利用CPU资源,提高程序的执行效率

1.1 多任务的概念

多任务是指在同一时间内执行多个任务

1.2 多任务的两种表现形式

并发
并行

1.3 并发

在一段时间内交替去执行多个任务
例子:对于单核CPU处理多任务,操作系统轮流让各个任务交替执行。
并发:任务数量大于CPU的核心数

1.4 并行

在一段时间内真正的同时一起执行多个任务
例子:对于多核CPU处理多任务,操作系统会给CPU的每个内核安排一个执行的任务,多个内核是真正的一起同时执行多个任务。这里需要注意多核CPU是并行的执行多任务,始终有多个任务一起执行。
并行:任务数量小于等于CPU的核心数

二、进程的介绍

2.1 程序中实现多任务的方式

在python中,想要实现多任务可以使用多进程

2.2 进程的概念

进程(Process)是资源分配的最小单位,是操作系统进行资源分配和调度运行的基本单位。
通俗理解:一个正在运行的一个程序就是一个进程。
例如:正在运行的qq、微信等,它们都是一个进程(运行的程序)
没有运行的程序就叫做程序。

一个程序运行后至少有一个进程。

2.3 多进程的作用

加快执行效率

三、多进程完成多任务

3.1 进程的创建步骤

1导入进程包

import multiprocessing

2通过进程类创建进程对象

进程对象 = multiprocessing.Process()

3启动进程执行任务

进程对象.start()

3.2 通过进程类创建进程对象

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

3.3 进程创建与启动的代码

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

3.4 例子

单任务

# 单任务.py
import time

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

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


if __name__ == '__main__':
    start_time = time.time()
    sing()
    dance()
    print(time.time() - start_time)

使用多进程实现多任务

# 使用多进程实现多任务.py

# 1 导入进程包
import multiprocessing
import time

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

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


if __name__ == '__main__':
    start_time = time.time()
    # 2 使用进程类创建进程对象
    # target 传入进程执行的函数名(名字即可)
    sing_process = multiprocessing.Process(target=sing)
    dance_process = multiprocessing.Process(target=dance)

    # 3 使用进程对象启动进程执行指定任务
    sing_process.start()
    dance_process.start()

    print(time.time() - start_time)

四、进程执行带有参数的任务

4.1 进程执行带有参数的任务

参数名 说明
args 以元组的方式给执行任务传参
kwargs 以字典方式给执行任务传参

4.2 args参数的使用

# target: 进程执行的函数名
# args: 表示以元组的方式给函数传参
sing_process = multiprocessing.Process(target=sing,args=(3,))
# 注意加了,才是元组,表示将3传给函数的参数
sing_process.start()

4.3 kwargs参数的使用

# target: 进程执行的函数名
# kwargs: 表示以字典的方式给函数传参
dance_process = multiprocessing.Process(target=dance,kwargs={"num":3} )
# 启动进程
dance_process.start()

例子

进程执行带有参数的任务

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

# 1 导入进程包
import multiprocessing
import time

# 唱歌
def sing(num):
    for i in range(num):
        print("唱歌...")
        time.sleep(0.5)

# 跳舞
def dance(num):
    for i in range(num):
        print("跳舞...")
        time.sleep(0.5)


if __name__ == '__main__':
    start_time = time.time()
    # 2 使用进程类创建进程对象
    # target 传入进程执行的函数名(名字即可)
    # args: 表示以元组的方式给函数传参
    # kwargs: 表示以字典的方式给函数传参
    sing_process = multiprocessing.Process(target=sing,args=(3,))
    dance_process = multiprocessing.Process(target=dance,kwargs={"num":2})

    # 3 使用进程对象启动进程执行指定任务
    sing_process.start()
    dance_process.start()

    print(time.time() - start_time)

程执行带有参数任务时注意事项

# 进程执行带有参数任务时注意事项.py

# 1 导入进程包
import multiprocessing
import time

# 唱歌
def sing(num,name):
    for i in range(num):
        print(name)
        print("唱歌...")
        time.sleep(0.5)

# 跳舞
def dance(num,name):
    for i in range(num):
        print(name)
        print("跳舞...")
        time.sleep(0.5)


if __name__ == '__main__':
    start_time = time.time()
    # 2 使用进程类创建进程对象
    # target 传入进程执行的函数名(名字即可)
    # args: 表示以元组的方式给函数传参
    #   元组的元素顺序就是任务的参数顺序
    # kwargs: 表示以字典的方式给函数传参
    #   key名就是参数的名字
    sing_process = multiprocessing.Process(target=sing,args=(3,"小明"))
    dance_process = multiprocessing.Process(target=dance,kwargs={"name":"小红","num":2})

    # 3 使用进程对象启动进程执行指定任务
    sing_process.start()
    dance_process.start()

    print(time.time() - start_time)

注意事项

元组传参一定要和参数顺序一致
字典方式传参时字典的key要和参数名一致

五、获取进程编号

进程编号的作用:
当程序中进程的数量越来越多时,如果没有办法区分主进程和子进程还有不同的子进程,那么就无法进行有效的进程管理,为了方便管理实际上每个进程都是有自己的编号的。

获取进程编号的两种方式:

1.获取当前进程编号

os.getpid()

2.获取当前父进程编号

os.getppid()

5.1 os.getpid()的使用

import os
pid = os.getpid()
print(pid)

5.2 os.getppid()的使用

def work():
	# 获取当前进程的编号
	print("work进程编号:",os.getpid())
	# 获取父进程的编号
	print("work父进程编号:",os.getppid())

例子

获取进程的编号

# 获取进程的编号.py

# 1 导入进程包
import multiprocessing
import time
import os

# 唱歌
def sing(num,name):
    print("唱歌进程的pid:",os.getpid())
    print("唱歌进程的父进程pid",os.getppid())
    for i in range(num):
        print(name,end="唱歌...\n")
        time.sleep(0.5)

# 跳舞
def dance(num,name):
    print("跳舞进程的pid:", os.getpid())
    print("跳舞进程的父进程pid", os.getppid())
    for i in range(num):
        print(name,end="跳舞...\n")
        time.sleep(0.5)


if __name__ == '__main__':
    print("主进程的pid",os.getpid())
    start_time = time.time()
    # 2 使用进程类创建进程对象
    # 创建子进程并指定执行的任务名
    # target 传入进程执行的函数名(名字即可)
    # args: 表示以元组的方式给函数传参
    #   元组的元素顺序就是任务的参数顺序
    # kwargs: 表示以字典的方式给函数传参
    #   key名就是参数的名字
    sing_process = multiprocessing.Process(target=sing,args=(3,"小明"))
    dance_process = multiprocessing.Process(target=dance,kwargs={"name":"小红","num":2})

    # 3 使用进程对象启动进程执行指定任务
    sing_process.start()
    dance_process.start()

    print(time.time() - start_time)

六、进程的注意点

主进程会等待所有的子进程执行结束再结束

6.1 主进程会等待所有的子进程执行结束再结束

def work():
    for i in range(10):
        print("工作中...")
        time.sleep(0.2)

if __name__ == '__main__':
	# 创建子进程
    work_process = multiprocessing.Process(target=work)
    work_process.start()
	# 让主进程等待1秒钟
    time.sleep(1)
    print("主进程执行完了")
    # 总结:主进程会等待所有的子进程执行结束再退出

例子

import time
import multiprocessing


def work():
    for i in range(10):
        print("工作中...")
        time.sleep(0.2)


if __name__ == '__main__':
    # 创建子进程
    work_process = multiprocessing.Process(target=work)
    work_process.start()
    # 让主进程等待1秒钟
    time.sleep(1)
    print("主进程执行完了")
    # 总结:主进程会等待所有的子进程执行结束再退出

6.2 设置守护主进程

主进程结束后不会再继续执行子进程中剩余的工作

def work():
    for i in range(10):
        print("工作中...")
        time.sleep(0.2)

if __name__ == '__main__':
	# 创建子进程
    work_process = multiprocessing.Process(target=work)
    # 设置守护主进程,主进程退出后子进程直接销毁,不再执行子进程的代码
    word_process.daemon = True
    work_process.start()
	# 让主进程等待1秒钟
    time.sleep(1)
    print("主进程执行完了")

例子

import time
import multiprocessing


def work():
    for i in range(10):
        print("工作中...")
        time.sleep(0.2)


if __name__ == '__main__':
    # 创建子进程
    work_process = multiprocessing.Process(target=work)
    # 设置守护主进程,主进程退出后子进程直接销毁,不再执行子进程的代码
    work_process.daemon = True
    work_process.start()
    # 让主进程等待1秒钟
    time.sleep(1)
    print("主进程执行完了")

6.3 知识要点

为了保证子进程能够正常的运行, 主进程会等所有的子进程执行完成以后再销毁,设置守护主进程的目的是主进程退出后子进程直接销毁,不再执行子进程的代码
设置守护主进程的方法

子进程对象.daemon=True

七、案例 多进程实现视频文件夹高并发copy器

需求分析

1.目标文件夹是否存在,如果不存在就创建,如果存在则不创建
2.遍历源文件夹中所有文件,并拷贝到目标文件夹
3.采用进程实现多任务,完成高并发拷贝

实现步骤

1.定义源文件夹所在的路径,目标文件夹所在路径

# 1 定义源文件夹所在的路径,目标文件夹所在路径
source_dir = "python教学视频"
dest_dir="/home/python/桌面/test"

2.创建目标文件夹

try:
	# 2 创建目标文件夹
	os.mkdir(dest_dir)
except:
	print("目标文件夹已经存在,未创建~")

3.通过os.listdir获取源目录中的文件列表

# 3 通过os.listdir获取源目录中的文件列表
file_list=os.listdir(source_dir)
print(file_list)

4.遍历每个文件,定义一个函数,专门实现文件拷贝

# 4 遍历每个文件,定义一个函数,专门实现文件拷贝
for file_name in file_list:
	copy_work(file_name,source_dir, dest_dir)

5.采用进程实现多任务,完成高并发拷贝

# 4 for循环依次拷贝每个文件
for file_name in file_list:
	# copy_work(file_name,source_dir, dest_dir)
	sub_process = multiprocessing.Processing(target=copy_work,args=(file_name,source_dir, dest_dir))
	sub_process.start()

实现

import os
import multiprocessing


def copy_file(file_name, source_dir, dest_dir):
    # 1 拼接源文件路径和目标文件路径
    source_path = source_dir + '\\' + file_name
    dest_path = dest_dir + '\\' + file_name
    print(source_path,"---->",dest_path)
    # 2 打开源文件和目标文件
    with open(source_path, 'rb') as source_file:
        with open(dest_path, 'wb') as dest_file:
            # 3 循环读取源文件到目标路径
            while True:
                data = source_file.read(1024)
                if data:
                    dest_file.write(data)
                else:
                    break


if __name__ == '__main__':
    # 1 定义源文件夹和目标文件夹
    source_dir = "源文件夹"
    dest_dir = "目标文件夹"

    # 2.创建目标文件夹
    try:
        os.mkdir(dest_dir)
    except:
        print("目标文件夹已经存在")

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

    # 4.遍历文件列表实现拷贝
    for file_name in file_list:
        # copy_file(file_name, source_dir, dest_dir)
        # 5.使用多进程实现多任务拷贝
        sub_process = multiprocessing.Process(target=copy_file, args=(file_name, source_dir, dest_dir))
        sub_process.start()

PS

下半部分链接

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值