PYTHON2.day07

野性酷女 2022-01-09 04:25 300阅读 0赞

前情回顾

  1. multiprocessing模块 创建进程

    基本创建进程: Process(target,args,kwargs,name)

    1. start()
    2. join(\[timeout\])

    进程对象属性:p.name p.pid p.daemon p.is_alive()

    自定义进程类:1. 继承Process,重写__init__

    1. 2. 重写run方法

    进程池: 大量进程事件需要较多进程处理,

    1. 此时进程池可以避免进程频繁创建销毁带来的系统消耗。
    2. Pool() 创建进程池对象
    3. apply\_async() 将事件使用进程池执行,async(异步)
    4. close() 关闭进程池,不能再添加新的事件了
    5. join() 回收进程池
    6. map() 使用迭代对象为指定函数传参后,加入进程池
  1. 进程间通信

    【1】管道 : Pipe() fd.recv() fd.send()

    【2】消息队列:Queue() q.get()获取消息 q.put() 存入消息

    1. q.full() q.empty() q.qsize() q.close()

ContractedBlock.gif ExpandedBlockStart.gif

  1. 1 import os
  2. 2 from multiprocessing import Process
  3. 3
  4. 4 filename = './he.jpg'
  5. 5
  6. 6 #获取文件大小
  7. 7 size = os.path.getsize(filename)
  8. 8
  9. 9 #复制上半部分
  10. 10 def top():
  11. 11 f = open(filename,'rb')
  12. 12 n = size // 2
  13. 13 fw = open("half_top.jpg",'wb')
  14. 14 while True:
  15. 15 if n < 1024:
  16. 16 data = f.read(n)
  17. 17 fw.write(data)
  18. 18 break
  19. 19 data = f.read(1024)
  20. 20 fw.write(data)
  21. 21 n -=1024
  22. 22 f.close()
  23. 23 fw.close()
  24. 24
  25. 25 #复制下半部分
  26. 26 def boot():
  27. 27 f = open(filename,'rb')
  28. 28 fw = open('half_bottom.jpg','wb')
  29. 29 f.seek(size//2,0)
  30. 30
  31. 31 while True:
  32. 32 data = f.read(1024)
  33. 33 if not data:
  34. 34 break
  35. 35 fw.write(data)
  36. 36 f.close()
  37. 37 fw.close()
  38. 38
  39. 39 t = Process(target = top)
  40. 40 b = Process(target = boot)
  41. 41 t.start()
  42. 42 b.start()
  43. 43 t.join()
  44. 44 b.join()

cope_file.py

************************************************************************************************************
一.进程间通信(续)
1.共享内存
【1】通信原理:在内存中开辟一块空间,进程可以写入内容和读取内容完成通信,
但是每次写入内容会覆盖之前的内容
【2】实现方法:
from multiprocessing import Value,Array

  1. obj = Value(ctype,data)
  2. 功能:开辟共享内存
  3. 参数:ctype 表示共享内存空间类型'i' 'f'浮点 'c'字符
  4. data 共享内存空间初始数据
  5. 返回值:共享内存对象
  6. obj.value 对该属性的修改或查看即对共享内存的读写
  7. obj = Array(ctype,data)
  8. 功能:开辟共享内存空间
  9. 参数:ctype 表示共享内存数据类型
  10. data 整数 则表示开辟空间的大小,
  11. 其他数据 开辟空间存放的初始化数据
  12. 返回值:共享内存对象
  13. Array共享内存读写:通过遍历obj可以得到的每个值,直接可以通过索引号修改任意值。

ContractedBlock.gif ExpandedBlockStart.gif

  1. 1 from multiprocessing import Process,Value
  2. 2 import time
  3. 3 import random
  4. 4
  5. 5 #创共享内存
  6. 6 money = Value('i',5000)
  7. 7
  8. 8 #操作共享内存
  9. 9 def man():
  10. 10 for i in range(30):
  11. 11 time.sleep(0.2)
  12. 12 money.value += random.randint(1,1000)
  13. 13
  14. 14 def girl():
  15. 15 for i in range(30):
  16. 16 time.sleep(0.16)
  17. 17 money.value -= random.randint(100,900)
  18. 18
  19. 19 m = Process(target=man)
  20. 20 g = Process(target=girl)
  21. 21 m.start()
  22. 22 g.start()
  23. 23 m.join()
  24. 24 g.join()
  25. 25
  26. 26 print("一月余额:",money.value)

value.py

1value

ContractedBlock.gif ExpandedBlockStart.gif

  1. 1 from multiprocessing import Process,Array
  2. 2 import time
  3. 3
  4. 4 #创建共享内存
  5. 5 #shm = Array('i',[1,2,3,4,5])
  6. 6
  7. 7 #创建共享内存,指定开辟空间大小
  8. 8 # shm =Array('i',6)
  9. 9
  10. 10
  11. 11 #存如字符串
  12. 12 shm = Array('c',b'Hello')
  13. 13
  14. 14
  15. 15 def fun():
  16. 16 for i in shm:
  17. 17 print(i)
  18. 18 # shm[2]=3000
  19. 19 shm[0] = b'h'
  20. 20
  21. 21 p = Process(target = fun)
  22. 22 p.start()
  23. 23 p.join()
  24. 24
  25. 25 for i in shm:
  26. 26 print(i,end=" ")
  27. 27 print(shm.value)#打印字符串

array_2.py

2array

ContractedBlock.gif ExpandedBlockStart.gif

  1. 1 from multiprocessing import Process,Array
  2. 2 import time
  3. 3
  4. 4 #创建共享内存
  5. 5 #shm = Array('i',[1,2,3,4,5])
  6. 6
  7. 7 #创建共享内存,指定开辟空间大小
  8. 8 # shm =Array('i',6)
  9. 9
  10. 10
  11. 11 #存如字符串
  12. 12 shm = Array('c',b'Hello')
  13. 13
  14. 14
  15. 15 def fun():
  16. 16 for i in shm:
  17. 17 print(i)
  18. 18 # shm[2]=3000
  19. 19 shm[0] = b'h'
  20. 20
  21. 21 p = Process(target = fun)
  22. 22 p.start()
  23. 23 p.join()
  24. 24
  25. 25 for i in shm:
  26. 26 print(i,end=" ")
  27. 27 print(shm.value)#打印字符串

array_3.py

2array\_3

ContractedBlock.gif ExpandedBlockStart.gif

  1. 1 from multiprocessing import Process,Array
  2. 2 import time
  3. 3
  4. 4
  5. 5 #创建共享内存,指定开辟空间大小
  6. 6 shm =Array('i',6)
  7. 7
  8. 8
  9. 9
  10. 10 def fun():
  11. 11 for i in shm:
  12. 12 print(i)
  13. 13 shm[2]=3000
  14. 14
  15. 15
  16. 16 p = Process(target = fun)
  17. 17 p.start()
  18. 18 p.join()
  19. 19
  20. 20 for i in shm:
  21. 21 print(i,end=" ")
  22. 22 print()

Array.py

2.信号量(信号灯集)
[1]通信原理:给定一个数量对多个进程可见。多个进程都可以操作该数量增减,并根据数量决定自己的行为
[2]实现方法
from multiprocessing import Semaphore

  1. sem = Semaphore(num)
  2. 功能:创建信号量对象
  3. 参数:信号量的初始值
  4. 返回值:信号量对象
  5. sem.acqire() 将信号量减1 当信号量为0时阻塞
  6. sem.release() 将信号量+1
  7. sem.get\_value()获取信号量数量

补充:当在父进程中创建套接字,进程间通信对象,文件对象,子进程从父进程获取这些对象时,那么对对象的操作
会有属性的相互关联影响。如果在各自进程中单独创建这些对象,则各自互不影响。

ContractedBlock.gif ExpandedBlockStart.gif

  1. 1 from multiprocessing import Semaphore,Process
  2. 2 from time import sleep
  3. 3 import os
  4. 4 #创建信号量
  5. 5 sem = Semaphore(3)
  6. 6
  7. 7 def fun():
  8. 8 print("%d 想执行事件"%os.getpid())
  9. 9 #想执行事件必须得到信号资源
  10. 10 sem.acquire()
  11. 11 print("%s 抢到了一个信号量,可以执行操作"%os.getpid())
  12. 12 sleep(3)
  13. 13 print("%d执行完事件再增加信号量"%os.getgid())
  14. 14 sem.release()
  15. 15 jobs=[]
  16. 16 for i in range(5):
  17. 17 p = Process(target = fun)
  18. 18 jobs.append(p)
  19. 19 p.start()
  20. 20
  21. 21 for i in jobs:
  22. 22 i.join()
  23. 23
  24. 24 print(sem.get_value())

3sem.py

3
二.线程编程(Thread)
1.什么是线程
【1】线程被称为轻量级的进程
【2】线程也可以使用计算机多核资源,是多任务编程方式
【3】线程是系统分配内核的最小单元
【4】线程可以理解为进程的分支任务

  1. 2.线程特征
  2. 1】一个进程中可以包含多个线程
  3. 2】线程也是一个运行行为,消耗计算机资源
  4. 3】一个进程中的所有线程共享这个进程的资源
  5. 4】多个线程之间的运行互不影响各自运行
  6. 5】线程的创建和销毁消耗资源远小于进程
  7. 6】各个线程有自己的ID等特征
  8. 3.创建线程threading模块
  9. 1】创建线程对象
  10. from threading import Thread
  11. t = Thread()
  12. 功能:创建线程对象
  13. 参数:target 绑定线程对象
  14. args 元组 给线程函数位置传参
  15. kwargs 字典 给线程函数键值传参
  16. 2】启动线程
  17. t.start()
  18. 3】回收线程
  19. t.join(\[timeout\])
  20. 4.线程对象属性:
  21. t.name 线程名称
  22. t.setName() 设置线程名称
  23. t.getName() 获取线程名称
  24. t.is\_alive() 查看线程是否在生命周期
  25. t.daemon 设置主线程和分支线程的 关系
  26. t.setDaemon() 设置daemon属性值
  27. t.isDaemon() 查看daemon属性值
  28. \*daemonTrue时主线程退出分支线程也退出。
  29. 要在start前设置,通常不和join一起使用

ContractedBlock.gif ExpandedBlockStart.gif

  1. 1 import threading
  2. 2 from time import sleep
  3. 3 import os
  4. 4
  5. 5 a=1
  6. 6 #线程函数
  7. 7 def music():
  8. 8 global a
  9. 9 print("a=",a)
  10. 10 for i in range(5):
  11. 11 sleep(2)
  12. 12 print("播放鱼",os.getpid())
  13. 13 a = 10000
  14. 14
  15. 15 #创建线程对象
  16. 16 t = threading.Thread(target = music)
  17. 17 t.start()
  18. 18
  19. 19 #主线程运行任务
  20. 20 for i in range(3):
  21. 21 sleep(3)
  22. 22 print("《大哥》",os.getpid())
  23. 23 t.join()
  24. 24 print("Main thread a:",a)

thread_1.py

4.1

ContractedBlock.gif ExpandedBlockStart.gif

  1. 1 from threading import Thread
  2. 2 from time import sleep
  3. 3
  4. 4 #含有参数的线程函数
  5. 5 def fun(sec,name):
  6. 6 print("线程函数传参")
  7. 7 sleep(sec)
  8. 8 print("%s 线程执行完毕"%name)
  9. 9
  10. 10 #创建多个线程
  11. 11 threads = []
  12. 12 for i in range(5):
  13. 13 t = Thread(target = fun,args=(2,),kwargs={'name':'T%d'%i})
  14. 14 threads.append(t)
  15. 15 t.start()
  16. 16
  17. 17 for i in threads:
  18. 18 i.join()

thread_2.py

4thread2

ContractedBlock.gif ExpandedBlockStart.gif

  1. 1 from threading import Thread
  2. 2 from time import sleep
  3. 3
  4. 4 def fun():
  5. 5 sleep(3)
  6. 6 print("线程属性测试")
  7. 7
  8. 8 # t = Thread(target = fun)
  9. 9 t = Thread(target = fun,name = 'Tarena')
  10. 10
  11. 11
  12. 12
  13. 13 #线程名称
  14. 14 t.setName('Tedu')#设置完会覆盖之间前的名称
  15. 15 print('Thread name:',t.name)
  16. 16 print("Thread name:",t.getName())
  17. 17
  18. 18
  19. 19 #设置daemon为True
  20. 20 t.setDaemon(True)
  21. 21 t.start()
  22. 22
  23. 23 #查看线程的生命周期
  24. 24 print("alive:",t.is_alive())
  25. 25 t.join()

thread_attr.py

4thread\_attr
5.自定义线程类:
【1】创建步骤

  1. 1. 继承Thread
  2. 2.重写\_\_init\_\_方法添加自己的属性,使用super加载父类属性
  3. 3.重写run方法
  4. 2】使用方法
  5. 1.实例化对象
  6. 2.调用start自动执行run方法
  7. 3.调用join回收线程

ContractedBlock.gif ExpandedBlockStart.gif

  1. 1 from threading import Thread
  2. 2 from time import sleep,ctime
  3. 3
  4. 4 class MyThread(Thread):
  5. 5 def __init__(self,target=None,args=(),kwargs={},name='Tedu'):
  6. 6 super().__init__()
  7. 7 self.target = target
  8. 8 self.args = args
  9. 9 self.kwargs = kwargs
  10. 10 self.name = name
  11. 11
  12. 12 def run(self):
  13. 13 self.target(*self.args,**self.kwargs)
  14. 14 def player(sec,song):
  15. 15 for i in range(2):
  16. 16 print("playing %s:%s"%(song,ctime()))
  17. 17 sleep(sec)
  18. 18
  19. 19 t = MyThread(target = player,args=(3,),kwargs={'song':'凉凉'},name='happy')
  20. 20
  21. 21 t.start()
  22. 22 t.join()

mythread.py

5mythread
三.线程通信
【1】通信方法:线程间使用全局变量间进行通信
【2】共享资源争夺
1.共享资源:多个进程或者线程都可以操作的资源成为公共资源,
对共享资源的操作代码段称为临界区。
2.影响:对共享资源的而无需操作可能会代来数据的混乱,或者操作错误。
此时往往需要同步互斥机制协调操作顺序。
【3】同步互斥机制
同步:同步是一种协作关系,为完成操作,多进程或者线程间形成一种协调,
按照必要的步骤有序执行操作。
互斥:是一种制约关系资源,当一个进程或者线程占有资源是会进行加锁处理,
此时其他进程线程就无法操作该资源,直到解锁后才能操作。

  1. 4】线程同步互斥方法
  2. 1.线程Event
  3. from threading import Event
  4. e = Event() 创建线程event对象
  5. e.wait(\[timeout\]) 阻塞等待eset
  6. e.set() 设置e,使wait结束阻塞
  7. e.clear() 使e回到未被设置的状态
  8. e.is\_set()查看当前e是否被设置

ContractedBlock.gif ExpandedBlockStart.gif

  1. 1 from threading import Event
  2. 2
  3. 3 #创建事件对象
  4. 4 e = Event()
  5. 5
  6. 6 e.set()#设置e
  7. 7 e.clear()#清楚set状态
  8. 8 print(e.is_set())#查看是否被设置
  9. 9 e.wait(3)#超时时间
  10. 10 print("-------------")

event_test.py

ContractedBlock.gif ExpandedBlockStart.gif

  1. 1 from threading import Thread,Event
  2. 2 from time import sleep
  3. 3
  4. 4 s = None#全局变量,用于通信
  5. 5 e = Event()
  6. 6
  7. 7 def foo():
  8. 8 sleep(0.1)
  9. 9 print("Foo 前来拜山头")
  10. 10 global s
  11. 11 s = "天王盖地虎"
  12. 12 e.set()#设置e
  13. 13
  14. 14 f = Thread(target = foo)
  15. 15 f.start()
  16. 16
  17. 17 #主线程验证口令
  18. 18 print("说对口令为自己人")
  19. 19 e.wait()#添加阻塞
  20. 20 if s == '天王盖地虎':
  21. 21 print("是自己人")
  22. 22 else:
  23. 23 print("不是自己人")
  24. 24
  25. 25 f.join()

theard_event.py

  1. 2.线程锁 Lock
  2. from threading import Lock
  3. lock = Lock()\#创建锁对象
  4. lock.acqire()\#上锁 如果lock已经上锁在调用会阻塞
  5. lock.release()\#解锁
  6. with lock: 上锁
  7. ...
  8. ...
  9. with代码块结束自动解锁

ContractedBlock.gif ExpandedBlockStart.gif

  1. 1 from threading import Thread,Lock
  2. 2
  3. 3 a = b = 0
  4. 4 lock = Lock()#锁对象
  5. 5 #一个线程
  6. 6 def value():
  7. 7 while True:
  8. 8 lock.acquire()
  9. 9 if a!=b:
  10. 10 print("a=%d,b=%d"%(a,b))
  11. 11 lock.release()
  12. 12
  13. 13 t = Thread(target=value)
  14. 14 t.start()
  15. 15 #另一个线程
  16. 16 while True:
  17. 17 while True:
  18. 18 with lock:
  19. 19 a +=1
  20. 20 b +=1
  21. 21
  22. 22 t.join()

theard_lock.py

作业:1.对比进程线程的特点区别
2.做单进程, 多进程, 多线程的效率测试
执行10遍 创建10个进程 创建10个线程
每个执行一遍 每个执行一遍

转载于:https://www.cnblogs.com/shengjia/p/10416284.html

发表评论

表情:
评论列表 (有 0 条评论,300人围观)

还没有评论,来说两句吧...

相关阅读

    相关 黑马python基础班---day07

    1:类属性:在类里面和方法外面定义的属性称为类属性,类属性属于当前类。 实例属性:(对象属性):在init方法里面定义的属性称为实例对象,实例属性属于某个对

    相关 python day07

    数据类型之间的相互转换 1、字符串转换成数字类型 判断哪些可以转换成数字型可以参考下面例题:  判断实现将所有能转换为数字类型的字符串都转换为对应类型的数字

    相关 Day07

    变量的访问原则和this关键字 1,变量的访问原则; 在方法中,使用一个变量时,会去找这个变量的声明和定义,寻找原则是,就近原则 2,就近原则: 在寻找变量定义

    相关 Python_day2

    homework: ''' 作业三用函数实现登录功能 1、让用户输入用户名与密码 2、校验用户名是否存在 3、用户名存在后检