python多线程编程笔记

python多线程编程笔记

资料:视频教程

时间:2021.8.31

一、进程

(一)、多任务介绍

多任务:同一时间内执行多个任务

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

两种方式

1、并发

image-20210831230856259

2、并行

image-20210831231148612

(二)、进程的介绍

进程是资源分配的最小单位,它是操作系统进行资源分配和调度运行的基本单位(eg:正在执行的程序就是一个进程)

(三)、多进程完成多任务

1、进程的创建步骤

  • 导入进程包

    • import multiprocessing
      
  • 通过进程类创建进程对象

    • 进程对象 = multiprocressing.Process(target=任务名)
      

      image-20210901150920141

  • 启动进程执行任务

    • 进程对象.start()
      
#1、导入包
import multiprocessing
import time
def sing():
    for i in range(3):
        print("唱歌……")
        time.sleep(0.3)
def dance():
    for j in range(3):
        print("跳舞……")
        time.sleep(0.3)


if __name__ == '__main__':
    #2、创建进程
    process_sing = multiprocessing.Process(target=sing)
    process_dance = multiprocessing.Process(target=dance)
    #3、开启进程
    process_dance.start()
    process_sing.start()

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

image-20210901153307619

注意:args传参要注意参数的先后顺序,kwargs传参要注意key的名字和参数名保持一致

#导入包
import multiprocessing
import time
def sing(num,name):
    print("%s唱歌"%name)
    for i in range(num):
        print("唱歌%d……"%i)
        time.sleep(0.3)
def dance(num):
    for j in range(num):
        print("跳舞%d……"%j)
        time.sleep(0.3)


if __name__ == '__main__':
    #创建进程
    # target :任务名字
    #args:以元组的方式给函数传参数
    #kwargs:以字典的方式给函数传参数
    #注意:args传参要注意参数的先后顺序,kwargs传参要注意key的名字和参数名保持一致
    process_sing = multiprocessing.Process(target=sing,args=(3,"zqq"))
    process_dance = multiprocessing.Process(target=dance,kwargs={"num":4})
    #开启进程
    process_dance.start()
    process_sing.start()

(四)、获取进程编号

1、获取进程编号的两种方式

  • 获取当前进程编号

    os.getpid()

  • 获取当前父进程编号

    os.getppid()

2、使用方法

  • 导包

    import os
    

    image-20210901161334809

    #导入包
    import multiprocessing
    import time
    import os
    #唱歌
    def sing(num,name):
        print("唱歌的进程pid",os.getpid())  #当前进程编号
        print("唱歌的主进程pid",os.getppid())  #父进程编号
        print("%s唱歌"%name)
        for i in range(num):
            print("唱歌%d……"%i)
            time.sleep(0.3)
    #跳舞
    def dance(num):
        print("跳舞的进程pid",os.getpid())
        print("跳舞的主进程pid",os.getppid())
        for j in range(num):
            print("跳舞%d……"%j)
            time.sleep(0.3)
    
    
    if __name__ == '__main__':
        print("主进程的pid:%d\n"%os.getpid(),"------"*10)
        #创建进程
        # target :任务名字
        #args:以元组的方式给函数传参数
        #kwargs:以字典的方式给函数传参数
        #注意:args传参要注意参数的先后顺序,kwargs传参要注意key的名字和参数名保持一致
        process_sing = multiprocessing.Process(target=sing,args=(3,"zqq"))
        process_dance = multiprocessing.Process(target=dance,kwargs={"num":4})
        #开启进程
        process_dance.start()
        process_sing.start()
    

(五)、进程的注意点

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

eg:

import multiprocessing
import time
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()

    time.sleep(1)
    print("主进程结束")

2、设置守护主进程(主进程)

进程对象.daemon = True

import multiprocessing
import time
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()
    time.sleep(1)
    print("主进程结束")

(六)、多任务的copy器

1、需求分析

  • 目标文件夹是否存在,如果存在就不创建文件夹,不存在则创建文件夹
  • 遍历源文件中所有文件,并拷贝到目标文件夹中
  • 采用进程实现多任务,完成高并发拷贝
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
    # 2、打开源文件和目标文件
    with open(source_path,"rb") as source_file:   #rb 二进制方式读取文件内容
        with open(dest_path,"wb") as dest_file:   #wb 二进制方式写入文件内容
    # 3、循环读取源文件到目标路径
            while True:
                data =  source_file.read(1024)
                if data:
                    dest_file.write(data)
                else:
                    break

if __name__ == '__main__':
    # 1、定义源文件和目标文件夹
    source_dir = r"G:\markdown\python"
    dest_dir = r"D:\python"
    # 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_list, source_dir, dest_dir)
        # 5、使用多进程实现多任务拷贝
        process = multiprocessing.Process(target=copy_file,args=(file_name,source_dir,dest_dir))
        process.start()

二、线程

(一)、线程的介绍

image-20210901180144768

image-20210901180748468

(二)、多线程完成多任务

1、线程的创建步骤

  • 导入线程模块

    import threading
    
  • 创建线程对象

    线程对象 = threading.Thread(target = 任务名)
    
  • 启动线程执行任务

    线程对象.start()
    
import time
import threading
def sing():
    for i in range(3):
        print("唱歌:",i)
        time.sleep(1)  #休息1s
def dance():
    for j in range(3):
        print("跳舞:",j)
        time.sleep(1)

if __name__ == '__main__':
    #sing()
    #dance()
    #创建线程
    sing_thread = threading.Thread(target = sing)
    dance_thread = threading.Thread(target = dance)
    #开启线程
    sing_thread.start()
    dance_thread.start()

(三)、线程执行带有参数的任务

image-20210901185131857

import time
import threading
def sing(num):
    for i in range(num):
        print("唱歌:",i)
        time.sleep(1)  #休息1s
def dance(num):
    for j in range(3):
        print("跳舞:",j)
        time.sleep(1)

if __name__ == '__main__':
    #创建线程
    #args:传参到函数中要注意参数顺序,参数是元组的方式
    #kwargs:以字典的方式进行传递,注意:参数名一定要与一致
    sing_thread = threading.Thread(target = sing,args=(3,))
    dance_thread = threading.Thread(target = dance,kwargs={"num":3})
    #开启线程
    sing_thread.start()
    dance_thread.start()

(四)、主线程和子线程的结束顺序

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

设置守护进程的两种方式:

  • 在创建线程时,加入daemon参数并为True

    threading.Thread(target=任务名,daemon=True)
    
  • 使用damon

    线程对象.demon = True
    
import threading
import time
def work():
    for i in range(10):
        print("工作中……",i)
        time.sleep(0.5)
if __name__ == '__main__':
    work_thread = threading.Thread(target=work,daemon=True)
    #方式一:设置守护线程
    # work_thread.daemon = True
    work_thread.start()
    time.sleep(4)
    print("主线程结束")

(五)、线程间的执行顺序

线程之间执行的顺序是无序的

  • 获取当前的线程信息,通过current_thread方法

    #通过current_thread()获取线程
    current_thread = threading.current_thread()
    #打印
    print(current_thread)
    
    import threading
    import time
    
    def task():
        time.sleep(1)
        thread = threading.current_thread()
        print(thread)
    
    if __name__ == '__main__':
        for i  in range(5):
            sub_thread = threading.Thread(target=task)
            sub_thread.start()
    #执行是无序的
    

(六)、进程和线程的对比

  1. 关系对比
    • 线程是依附在进程里面的,没有进程就没有线程
    • 一个进程默认提供一条线程,进程可以创建多个线程

image-20210901200219160

  1. 区别对比

    • 创建进程的资源开销要比创建线程的资源开销要大
    • 进程是操作系统资源分配的基本单位,线程是cpu调度的基本单位
    • 线程不能够单独执行,必须依存在进程中
  2. 优缺点

    image-20210901200626179

(七)、多进程高并发的copy器

import os
import threading
def copy_file(file_name,source_dir,dest_dir):
    # 1、拼接源文件夹路径和目标文件夹路径
    source_path = source_dir+"/"+file_name
    dest_path = dest_dir+"/"+file_name
    # 2、打开源文件和目标文件
    with open(source_path,"rb") as source_file:   #rb 二进制方式读取文件内容
        with open(dest_path,"wb") as dest_file:   #wb 二进制方式写入文件内容
    # 3、循环读取源文件到目标路径
            while True:
                data =  source_file.read(1024)
                if data:
                    dest_file.write(data)
                else:
                    break

if __name__ == '__main__':
    # 1、定义源文件和目标文件夹
    source_dir = r"G:\markdown\python"
    dest_dir = r"D:\python"
    # 2、创建目标文件夹
    try:
        os.mkdir(dest_dir)
    except:
        print("目标文件已经存在了")
    # 3、读取源文件的文件列表
    file_list = os.listdir(source_dir)

    # 4、遍历文件列表实现拷贝
    for file_name in file_list:
        thread =  threading.Thread(target=copy_file,args=(file_name,source_dir,dest_dir))
        thread.start()
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值