Python【day8】:Python学习(异常处理、SocketServer实现多并发、进程、线程介绍、threading实例、线程锁、GIL、Event、信号量、红绿灯、multiprocess实例、进程间通讯、队列Queue)

异常处理

# isinstance(obj, cls)
# 检查是否obj是否是类 的对象
class Foo(object):
pass
obj = Foo()
print(isinstance(obj, Foo)) #True

# issubclass(sub, super)
# 检查sub类是否是 super 类的派生类
class Foo(object):
pass
class Bar(Foo):
pass
print(issubclass(Bar, Foo)) #True

# 需求:将用户输入的两个数字相加
while True:
num1 = input('num1:')
num2 = input('num2:')
try:
num1 = int(num1)
num2 = int(num2)
result = num1 + num2
except Exception as e: #35用as 27用逗号
print('出现异常,信息如下:') #异常的头子,可以加红色颜色
print(e) #e是异常具体信息
# 如果输入是不是数字,invalid literal for int() with base 10: 'aa'

# 异常种类
# python中的异常种类非常多,每个异常专门用于处理某一项异常!!!
#
# AttributeError 试图访问一个对象没有的树形,比如foo.x,但是foo没有属性x
# IOError 输入/输出异常;基本上是无法打开文件
# ImportError 无法引入模块或包;基本上是路径问题或名称错误
# IndentationError 语法错误(的子类) ;代码没有正确对齐
# IndexError 下标索引超出序列边界,比如当x只有三个元素,却试图访问x[5]
# KeyError 试图访问字典里不存在的键
# KeyboardInterrupt Ctrl+C被按下
# NameError 使用一个还未被赋予对象的变量
# SyntaxError Python代码非法,代码不能编译(个人认为这是语法错误,写错了)
# TypeError 传入对象类型与要求的不符合
# UnboundLocalError 试图访问一个还未被设置的局部变量,基本上是由于另有一个同名的全局变量,导致你以为正在访问它
# ValueError 传入一个调用者不期望的值,即使值的类型是正确的

# 1 IndexError  索引错误,一般是索引越界
dic = ["wupeiqi", 'alex']
try:
dic[10] #字典只有2个值,索引号却是10,索引越界
except IndexError as e:
print("索引异常:",e) #索引异常: list index out of range

#2 KeyError
dic = {'k1':'v1'}
try:
dic['k20'] #字典中不存在键 k20
except KeyError as e:
print("键错误:",e) #键错误: 'k20'

#3 ValueError
s1 = 'hello'
try:
int(s1) #字符串是不能转换成整数的
except ValueError as e:
print("值错误",e) #值错误 invalid literal for int() with base 10: 'hello'

#4 对于特殊处理或提醒的异常需要先定义,最后定义Exception来确保程序正常运行
s1 = 'hello'
try:
int(s1)
except KeyError as e:
print('键错误')
except IndexError as e:
print('索引错误')
except Exception as e:
print('错误') #错误 这个应该是ValueError 前面没有单独定义,最后被Exception捕捉到了

#5 异常其他结构
try:
# 主代码块
pass
except KeyError as e:
# 异常时,执行该块
pass
else:
# 主代码块执行完,才执行该块(如果有异常56行,就不执行该处代码)
#一般在这里写测试代码,提示前面的代码测试通过
pass
finally:
# 无论异常与否,最终执行该块
#应用场景:一般在这里执行文件关闭,socket关闭,或者其他清理工作
pass

#6 主动触发异常
try:
raise Exception('错误了。。。')
##应用场景:主要是一些业务场景(系统不会有),例如atm取款余额不够了之类业务相关
except Exception as e:
print(e) #错误了。。。

#7 自定义异常
class WupeiqiException(Exception): #这个异常类继承Exception
def __init__(self, msg):
self.message = msg #将参数传到实例
def __str__(self):
# print(self.message)
return self.message #print实例会得到这里的return值---__str__
try:
raise WupeiqiException('我的异常')
#这里类名(参数)就是一个实例,这个实例返回的是81行 __str__的返回值,返回的是参数值
except WupeiqiException as e: #这里的类WupeiqiException 继承 Exception
print(e) #我的异常

obj = WupeiqiException("面向对象,自定义异常")
print(obj) #面向对象,自定义异常

#8 加上断言
class WupeiqiException(Exception):
def __init__(self, msg):
self.message = msg
def __str__(self):
return self.message
try:
a = 1
assert a == 1 #断言,判断后面的条件是否正确,不是True,报错 AssertionError
# #应用场景:这个步骤至关重要,必须是True,否则后面的代码无法执行
raise WupeiqiException('我的异常') #主动触发异常 #应用场景:主要是一些业务场景(系统不会有)
#主动触发的异常放在try中
except WupeiqiException as e:
print(e) #我的异常
else: ## 主代码块执行完,执行该块,前面如果没有错误 应用场景:测试代码
print("没有错误") #没有错误 #前面如果没有出现异常,就执行else(如果有异常,这个else就不执行)
#将101注释,这个else就执行,如果101行不注释,这个else就执行
finally: #应用场景:一些清理工作,比如socket异常关闭了,还是可以执行一些清理工作
# 无论异常与否,最终执行该块
pass
print("finally") #finally

多线程

#进程和线程的定义和区别

# Python threading模块
# 线程有2种调用方式,如下:

#1直接调用
import threading
import time

def sayhi(num): #定义每个线程要运行的函数
print("running on number:%s" % num)
#running on number:1 #线程1打印
#running on number:2 #线程2打印
time.sleep(3) #2个线程,都是3秒后执行完毕 出现code 0

if __name__ == "__main__":
pass
t1 = threading.Thread(target=sayhi,args=(1,))
#生成一个线程实例,第一个参数sayhi后面不要括号(指定线程要允许的函数),
# 第二个参数是sayhi传入的实参(只有1个实参,需要加逗号)
t2 = threading.Thread(target=sayhi,args=(2,))

t1.start() #启动一个线程
t2.start() #启动线程2

print(t1.getName()) #获取线程名 Thread-1 线程1的名字
print(t2.getName()) #Thread-2 线程1的名字

#2 继承式调用(继承类threading.Thread)
import threading
import time

class MyThread(threading.Thread):
def __init__(self,num):
# threading.Thread.__init__(self) #继承父类的构造方法--经典类写法
super(MyThread,self).__init__() #继承父类的构造方法--新式类写法
self.num = num #将参数传给实例

def run(self):#定义每个线程要运行的函数,函数名必须是run,不能是其他
print("running on num:%s" % self.num)
#running on num:1 #线程1打印
#running on num:2 #线程2打印
time.sleep(3) #2个线程,都是3秒后执行完毕 出现code 0

if __name__ == "__main__":
t3 = MyThread(1) #创建线程实例1
t4 = MyThread(2) #创建线程实例2
t3.start() #启动线程1
t4.start() #启动线程2

#3 一次创建2个线程 join
import threading
import time

def sayhi(num):
print("running on number %s" % num)
time.sleep(3)

if __name__ == "__main__":
t1 = threading.Thread(target=sayhi,args=(1,))
t2 = threading.Thread(target=sayhi,args=(2,))

t1.start() #running on number 1
t2.start() #running on number 2

print(t1.getName()) #Thread-1
print(t2.getName()) #Thread-2

t1.join()
t2.join() #一共3个线程(3个线程独立),主线程创建了t1,t2两个线程,主线程等t1 t2执行完毕后,才执行74行
print("---main---") #主线程执行的
#如果72 73行注释掉,那么就是3个线程(主线程,子线程t1 t2)同时执行,主线程不会等待t1 t2执行完毕,才执行74行

#1 一次批量创建5个线程 --遍历创建
import threading
import time

def sayhi(num):
print("running on number %s" % num)
time.sleep(3)

if __name__ == "__main__":
for i in range(5):
t = threading.Thread(target=sayhi,args=(i,)) #创建5个线程
t.start() #启动线程

#2 一次批量创建5个线程 --遍历创建 join(加上这个主线程会等待子线程执行完毕后,才运行)
import threading
import time

def sayhi(num):
print("running on number %s" % num)
time.sleep(2) #子线程执行后,会休眠2秒

if __name__ == "__main__":
for i in range(5):
t = threading.Thread(target=sayhi,args=(i,)) #创建5个线程
t.start() #启动线程
t.join() #等5个子线程全部执行完毕后,休眠2秒,主线程才执行31行,这里主线程创建5个子线程,主线程和5个子线程完全独立运行
#Wait until the thread terminates.
print("---main---")

#3 一次批量创建5个线程 --遍历创建 join(加上这个主线程会等待子线程依次执行完毕后,才运行)
import threading
import time

def sayhi(num):
print("running on number %s" % num)
time.sleep(2) #子线程执行后,会休眠2秒

if __name__ == "__main__":
for i in range(5):
t = threading.Thread(target=sayhi,args=(i,)) #创建5个线程
t.start() #启动线程
t.join() #等5个子线程依次全部执行完毕后,休眠2秒,主线程才执行31行,这里主线程创建5个子线程,主线程和5个子线程完全独立运行
#这里t.join()是和t.star()同一级别,相当于5个子线程是不是并发,而是依次串行执行完毕后,休眠2秒,执行主线程的48行
#Wait until the thread terminates.
print("---main---")

#多线程 join
import threading
import time

def sayhi(num): #定义每个线程要运行的函数
print("running on number:%s" %num)
time.sleep(3)
if __name__ == '__main__':
'''
t1 = threading.Thread(target=sayhi,args=(1,)) #生成一个线程实例
t2 = threading.Thread(target=sayhi,args=(2,)) #生成另一个线程实例
t1.start() #启动线程
t2.start() #启动另一个线程
print(t1.getName()) #获取线程名
print(t2.getName())
t1.join() #t2.wait()
t2.join() #t2.wait()'''
t_list = []
for i in range(10):
t = threading.Thread(target=sayhi,args=(i,)) #args后的小括号和中括号效果是一样的
t.start()
t_list.append(t)
# t.join()
for i in t_list: #26 27行的for循环相当于 25行
i.join()
print('---main---') #主线程等10个子线程全部执行完毕后,休眠2秒,开始执行28行

# 2多线程 join  单独创建主线程
import time
import threading

def run(n): #定义多线程调用的函数
print("[%s]-----running-----" % n) #子线程打印
time.sleep(2)
print("-----done-----")

def main(): #定义创建5个子线程的函数
for i in range(5):
t = threading.Thread(target=run,args= (i,)) #创建5个子线程
t.start() #启动5个子线程
t.join() #5个子线程串行执行完毕后,才执行23行的主线程
#如果16行注释掉,结果就是5个子线程并行同时执行完毕后,才执行23行的主线程
print("starting thread",t.getName())

m = threading.Thread(target=main,args = ()) #创建1个主线程
# m.setDaemon(True) #将主线程设置为Daemon线程,它退出时,其它子线程会同时退出,不管是否执行完任务
m.start() #启动主线程
m.join() #5个子线程串行执行完毕后,才执行24行的主线程
print("--main thread done----") #主线程打印

#多线程 守护进程
import time
import threading

def run(n): #定义多线程调用的函数
print("[%s]-----running-----" % n) #子线程打印
time.sleep(2)
print("-----done-----")

def main(): #定义创建5个子线程的函数
for i in range(5):
t = threading.Thread(target=run,args= (i,)) #创建5个子线程
t.start() #启动5个子线程
t.join()
print("starting thread",t.getName())

m = threading.Thread(target=main,args = ()) #创建1个主线程
m.setDaemon(True) #将主线程设置为Daemon线程,它退出时,其它子线程会同时退出,不管是否执行完任务
m.start() #启动主线程
# m.join()
print("--main thread done----") #主线程打印

# 输出
#--main thread done----
# [0]-----running-----

线程锁
#需求:100个子线程依次取到100,每个子线程进行-1操作,最后的结果如果不存在冲掉的情况,应该是0
# 不加互斥锁的话,可能会出现子线程a的执行结果覆盖了子进程b的结果,最后的值可能不是0
# 为了避免子进程之间结果互相覆盖的情况,需要加上线程锁(互斥锁),保证同一时刻,只能一个子线程修改num

#没加线程锁的情况
import time
import threading

num = 100 #设定一个共享变量(全局变量)

def addnum(): #每个线程调用的函数
global num #在每个线程中都获取这个全局变量 (调用全局变量,必须加上global 否则编译不过)
print("---get num:",num) #---get num: 100
time.sleep(2)
num -=1 #对全局变量进行-1操作

thread_list = [] #创建一个空列表
for i in range(100):
t = threading.Thread(target=addnum) #创建100个线程,调用的是addnum
t.start() #启动所有线程
thread_list.append(t) #每创建一个子线程,将子线程加入到列表

for j in thread_list: #遍历100个子线程的列表
j.join() #主线程会等待100个子线程执行完毕后,才执行24

print("final num",num) #final num 0

#需求:100个子线程依次取到100,每个子线程进行-1操作,最后的结果如果不存在冲掉的情况,应该是0
# 不加互斥锁的话,可能会出现子线程a的执行结果覆盖了子进程b的结果,最后的值可能不是0
# 为了避免子进程之间结果互相覆盖的情况,需要加上线程锁(互斥锁),保证同一时刻,只能一个子线程修改num

#不加线程锁的情况--2
import time
import threading

num = 100 #设定一个共享变量(全局变量)

def addnum(): #每个线程调用的函数
global num #在每个线程中都获取这个全局变量 (调用全局变量,必须加上global 否则编译不过)
print("---get num:",num) #---get num: 100
time.sleep(2)

num -=1 #对全局变量进行-1操作


for i in range(100):
t = threading.Thread(target=addnum) #创建100个线程,调用的是addnum
t.start() #启动所有线程
t.join() #主线程会等待100个子线程并行同时执行完毕后,才执行29行,注意t.join()如果放在t.start()同级,就是串行执行
#100个子线程后,再执行主线程29行

print("final num",num) #final num 0


#需求:100个子线程依次取到100,每个子线程进行-1操作,最后的结果如果不存在冲掉的情况,应该是0
# 不加互斥锁的话,可能会出现子线程a的执行结果覆盖了子进程b的结果,最后的值可能不是0
# 为了避免子进程之间结果互相覆盖的情况,需要加上线程锁(互斥锁),保证同一时刻,只能一个子线程修改num

#3加线程锁的情况 lock.acquire() lock.release()
import time
import threading

num = 100 #设定一个共享变量(全局变量)

def addnum(): #每个线程调用的函数
global num #在每个线程中都获取这个全局变量 (调用全局变量,必须加上global 否则编译不过)
print("---get num:",num) #---get num: 100
# lock.acquire() #锁如果加载这里,那么需要等待200秒 才会有结果
time.sleep(2)
lock.acquire() #修改前加上互斥锁 互斥锁加完后 需要马上释放,不然影响性能
#全局锁可以在函数内使用,但是不能修改
num -=1 #对全局变量进行-1操作
lock.release() #修改后释放锁

thread_list = [] #创建一个空列表
lock = threading.Lock() #生成全局互斥锁
for i in range(100):
t = threading.Thread(target=addnum) #创建100个线程,调用的是addnum
t.start() #启动所有线程
thread_list.append(t) #每创建一个子线程,将子线程加入到列表

for j in thread_list: #遍历100个子线程的列表
j.join() #主线程会等待100个子线程执行完毕后,才执行24

print("final num",num) #final num 0

递归锁
__author__ = 'Administrator'
#-*- coding:utf-8 -*-

# RLock(递归锁)
# 说白了就是在一个大锁中还要再包含子锁

import threading,time

def run1():
print("grab the first part data")
lock.acquire()
global num
num +=1
lock.release()
return num
def run2():
print("grab the second part data")
lock.acquire()
global num2
num2+=1
lock.release()
return num2
def run3(): #定义每个线程调用的函数
lock.acquire()
res = run1()
print('--------between run1 and run2-----')
res2 = run2()
lock.release()
print(res,res2) #10 10


if __name__ == '__main__':
num,num2 = 0,0
lock = threading.RLock() #定义递归锁
for i in range(10):
t = threading.Thread(target=run3) #创建100个子线程,指定调用run3函数,不带小括号
t.start() #启动子线程

while threading.active_count() != 1: #活动子线程的个数 不是1 代表还没有运行完
print(threading.active_count()) #打印当前还有多少子线程在运行
else:
print('----all threads done---')
print(num,num2) #10 10

信号量
# Semaphore(信号量)
# 互斥锁 同时只允许一个线程更改数据,而Semaphore是同时允许一定数量的线程更改数据(比如3个) ,
# 比如餐馆有3个位置,那最多只允许3个人就餐,后面的人只能等里面有人出来了才能再进去。

import threading,time

def run(n):
pass
semaphore1.acquire()
time.sleep(2)
print("run the thread:%s" % n)
semaphore1.release()

if __name__ == '__main__':
pass
num = 0
semaphore1 = threading.BoundedSemaphore(3)
#最多允许5个线程同时运行
for i in range(20): #创建20个线程
t = threading.Thread(target=run,args =(i,))
t.start() #启动所有线程

while threading.active_count() !=1:
pass
else:
print("all thread done----")
print(num)

#一共20个子线程,每次运行3个,间隔2秒后,再运行3个。。。。

线程锁
#需求:100个子线程依次取到100,每个子线程进行-1操作,最后的结果如果不存在冲掉的情况,应该是0
# 不加互斥锁的话,可能会出现子线程a的执行结果覆盖了子进程b的结果,最后的值可能不是0
# 为了避免子进程之间结果互相覆盖的情况,需要加上线程锁(互斥锁),保证同一时刻,只能一个子线程修改num

#没加线程锁的情况
import time
import threading

num = 100 #设定一个共享变量(全局变量)

def addnum(): #每个线程调用的函数
global num #在每个线程中都获取这个全局变量 (调用全局变量,必须加上global 否则编译不过)
print("---get num:",num) #---get num: 100
time.sleep(2)
num -=1 #对全局变量进行-1操作

thread_list = [] #创建一个空列表
for i in range(100):
t = threading.Thread(target=addnum) #创建100个线程,调用的是addnum
t.start() #启动所有线程
thread_list.append(t) #每创建一个子线程,将子线程加入到列表

for j in thread_list: #遍历100个子线程的列表
j.join() #主线程会等待100个子线程执行完毕后,才执行24

print("final num",num) #final num 0


#需求:100个子线程依次取到100,每个子线程进行-1操作,最后的结果如果不存在冲掉的情况,应该是0
# 不加互斥锁的话,可能会出现子线程a的执行结果覆盖了子进程b的结果,最后的值可能不是0
# 为了避免子进程之间结果互相覆盖的情况,需要加上线程锁(互斥锁),保证同一时刻,只能一个子线程修改num

#不加线程锁的情况--2
import time
import threading

num = 100 #设定一个共享变量(全局变量)

def addnum(): #每个线程调用的函数
global num #在每个线程中都获取这个全局变量 (调用全局变量,必须加上global 否则编译不过)
print("---get num:",num) #---get num: 100
time.sleep(2)

num -=1 #对全局变量进行-1操作


for i in range(100):
t = threading.Thread(target=addnum) #创建100个线程,调用的是addnum
t.start() #启动所有线程
t.join() #主线程会等待100个子线程并行同时执行完毕后,才执行29行,注意t.join()如果放在t.start()同级,就是串行执行
#100个子线程后,再执行主线程29行

print("final num",num) #final num 0

#需求:100个子线程依次取到100,每个子线程进行-1操作,最后的结果如果不存在冲掉的情况,应该是0
# 不加互斥锁的话,可能会出现子线程a的执行结果覆盖了子进程b的结果,最后的值可能不是0
# 为了避免子进程之间结果互相覆盖的情况,需要加上线程锁(互斥锁),保证同一时刻,只能一个子线程修改num

#加线程锁的情况 lock.acquire() lock.release()
import time
import threading

num = 100 #设定一个共享变量(全局变量)

def addnum(): #每个线程调用的函数
global num #在每个线程中都获取这个全局变量 (调用全局变量,必须加上global 否则编译不过)
print("---get num:",num) #---get num: 100
# lock.acquire() #锁如果加载这里,那么需要等待200秒 才会有结果
time.sleep(2)
lock.acquire() #修改前加上互斥锁 互斥锁加完后 需要马上释放,不然影响性能
#全局锁可以在函数内使用,但是不能修改
num -=1 #对全局变量进行-1操作
lock.release() #修改后释放锁

thread_list = [] #创建一个空列表
lock = threading.Lock() #生成全局互斥锁
for i in range(100):
t = threading.Thread(target=addnum) #创建100个线程,调用的是addnum
t.start() #启动所有线程
thread_list.append(t) #每创建一个子线程,将子线程加入到列表

for j in thread_list: #遍历100个子线程的列表
j.join() #主线程会等待100个子线程执行完毕后,才执行24

print("final num",num) #final num 0


递归锁
# RLock(递归锁)
# 说白了就是在一个大锁中还要再包含子锁

import threading,time

def run1():
print("grab the first part data")
lock.acquire()
global num
num +=1
lock.release()
return num
def run2():
print("grab the second part data")
lock.acquire()
global num2
num2+=1
lock.release()
return num2
def run3(): #定义每个线程调用的函数
lock.acquire()
res = run1()
print('--------between run1 and run2-----')
res2 = run2()
lock.release()
print(res,res2) #10 10


if __name__ == '__main__':
num,num2 = 0,0
lock = threading.RLock() #定义递归锁
for i in range(10):
t = threading.Thread(target=run3) #创建100个子线程,指定调用run3函数,不带小括号
t.start() #启动子线程

while threading.active_count() != 1: #活动子线程的个数 不是1 代表还没有运行完
print(threading.active_count()) #打印当前还有多少子线程在运行
else:
print('----all threads done---')
print(num,num2) #10 10


多进程
#多进程--定义

from multiprocessing import Process
import time

def f(name): #每个进程调用的函数
time.sleep(1)
print("hello",name)

if __name__ == '__main__':
for i in range(3):
i = Process(target=f,args=(i,)) #创建3个子进程
i.start() #启动所有进程
# p = Process(target=f,args=("jack",)) #创建进程
# p2 = Process(target=f,args=("jack2",)) #创建进程
# p.start() #启动进程
# p2.start() #启动进程
# p.join()

#多进程,显示父进程和子进程的id

from multiprocessing import Process
import os
def info(title): #显示相关信息
print(title)
print("module name:",__name__) #显示模块名字
print("parent process:",os.getppid()) #打印当前进程的父进程的id
print("process id:",os.getpid()) #打印当前进程的id
print("=====================")

def f(name): #每个进程调用的函数
info("function") #调用函数info
print("hello",name)

if __name__ == '__main__':
info("main process") #调用函数info 显示父进程和当前进程的id
for i in range(2):
i = Process(target=f,args= (i,)) #创建2个进程
i.start() #启动进程

# main process
# module name: __main__
# parent process: 1292 #pycharm的进程id
# process id: 25256 #主进程id
# =====================
# function
# module name: __mp_main__
# parent process: 25256 ##主进程id
# process id: 27528 #子进程id
# =====================
# hello bob

# 进程间通讯  
# 不同进程间内存是不共享的,要想实现两个进程间的数据交换,可以用以下方法:
#
# Queues (先进先出,put到队列 getongoing队列中取
#
# 使用方法跟threading里的queue差不多

#需求:2个子进程将列表put放到队列中,然后get从队列中取出来
# 进程间是无法直接交换数据的,可以通过第三方(例如:队列)实现进程间数据的间接交换
from multiprocessing import Process, Queue

def f(q): #定义每个进程调用的函数
q.put([42, None, 'hello']) #

if __name__ == '__main__':
q = Queue() #创建队列
for i in range(2): #创建2个子进程
i = Process(target=f, args=(q,))
i.start() #启动子2个进程
print(q.get()) # prints "[42, None, 'hello']"
# i.join()

#需求:2个子进程将列表通过子连接a发送给父连接b的形式 (send recv close)
# 进程间是无法直接交换数据的,可以通过第三方(例如:队列queue、管道pipe)实现进程间数据的间接交换
from multiprocessing import Process, Pipe

def f(conn): #每个子进程调用的函数
conn.send([42, None, 'hello'])
conn.close()

if __name__ == '__main__':
parent_conn, child_conn = Pipe() #创建管道实例
for i in range(2):
i = Process(target=f, args=(child_conn,)) #创建2个子进程
i.start() #启动子进程
print(parent_conn.recv()) # prints "[42, None, 'hello']"
# i.join()

# A manager returned by Manager() will support types list, dict, Namespace, Lock, RLock,\
# Semaphore, BoundedSemaphore,Condition, Event, Barrier, Queue, Value and Array.

from multiprocessing import Process, Manager

def f(d, l):
d[1] = '1'
d['2'] = 2
d[0.25] = None
l.append(1) #10个子进程每次给列表追加1
print(l)

if __name__ == '__main__':
with Manager() as manager: #定义Manager实例
d = manager.dict() #字典方法
l = manager.list(range(5)) #列表方法 [0, 1, 2, 3, 4]
p_list = [] #定义空列表
for i in range(10): #创建10个进程
p = Process(target=f, args=(d, l))
p.start() #启动10个子进程
p_list.append(p) #将子进程依次添加到空列表
for res in p_list: #遍历子进程列表
res.join() #等待每个子进程全部执行完毕

print(d) #主进程打印字典 {'2': 2, 1: '1', 0.25: None}
print(l) #主进程打印列表[0, 1, 2, 3, 4, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1] 10个1追加


#进程同步--进程锁

from multiprocessing import Process, Lock

def f(l, i): #每个子进程调用的函数 传入2个参数
l.acquire() #加上进程锁
try:
print('hello world', i)
finally:
l.release() #释放进程锁(这个finally设置必须会执行,否则锁一直不释放)

if __name__ == '__main__':
lock = Lock() #定义全局进程锁
for num in range(10): #创建10个进程
# Process(target=f, args=(lock, num)).start()
num = Process(target=f, args=(lock, num)) #上面16行相当于17+18行
num.start()


# 进程池  
# 进程池内部维护一个进程序列,当使用时,则去进程池中获取一个进程,如果进程池序列中没有可供使用的进进程,
# 那么程序就会等待,直到进程池中有可用进程为止。
#
# 进程池中有两个方法:
#
# apply
# apply_async

from multiprocessing import Process,Pool,freeze_support
import time

def Foo(i): #每个进程要调用的函数
time.sleep(2)
return i+100

def Bar(arg): #18行返回的值自动传到arg中
print('-->exec done:',arg)

if __name__ == '__main__':
freeze_support() #固定写法
pool = Pool(5) #设置进程池是5 运行每次最多同时运行5个进程
for i in range(10): #创建10个进程
# pool.apply_async(func=Foo, args=(i,),callback=Bar)
#参数1是指定调用哪个函数,参数2是传入的实参,参数3是指指定函数调用完毕后,调用第三个参数
pool.apply(func=Foo, args=(i,))

print('end')
pool.close() #关闭进程池 这里的close正常应该在join之后,但是这里特殊,固定写法,记住背下来
pool.join()#进程池中进程执行完毕后再关闭,如果注释,那么程序直接关闭。


Events
红绿灯

# 事件-Events
# 一个事件是一个简单的同步对象;
# 事件代表一个内部标志,线程
# 可以等待标志设置,或设置或清除标志自己。
# event = threading.Event()
# #客户端线程可以等待标志被设置
# event.wait()
# #服务器线程可以设置或重置
# event.set()
# event.clear()
# 如果标志是设置,等待方法没有做任何事情。
# 如果被清除,等到它再次被设置。
# 任何数目的线程可以等待相同的事件。

#红绿灯例子

# Events
#
# An event is a simple synchronization object;
#
# the event represents an internal flag, and threads
# can wait for the flag to be set, or set or clear the flag themselves.
#
# event = threading.Event()
#
# # a client thread can wait for the flag to be set
# event.wait()
#
# # a server thread can set or reset it
# event.set()
# event.clear()
# If the flag is set, the wait method doesn’t do anything.
# If the flag is cleared, wait will block until it becomes set again.
# Any number of threads may wait for the same event.
#
# 通过Event来实现两个或多个线程间的交互,下面是一个红绿灯的例子,即起动一个线程做交通指挥灯,
# 生成几个线程做车辆,车辆行驶按红灯停,绿灯行的规则。


# Python提供了Event对象用于线程间通信,它是由线程设置的信号标志,如果信号标志为真,则其他线程等待直到信号接触。
# Event对象实现了简单的线程通信机制,它提供了设置信号,清楚信号,等待等用于实现线程间的通信。
# 1 设置信号
# 使用Event的set()方法可以设置Event对象内部的信号标志为真。
# Event对象提供了isSet()方法来判断其内部信号标志的状态。
# 当使用event对象的set()方法后,isSet()方法返回真
# 2 清除信号
# 使用Event对象的clear()方法可以清除Event对象内部的信号标志,即将其设为假,当使用Event的clear方法后,
# isSet()方法返回假
# 3 等待
# Event对象wait的方法只有在内部信号为真的时候才会很快的执行并完成返回。当Event对象的内部信号标志为假时,
# 则wait方法一直等待到其为真时才返回。

#set 绿灯 车走
#clear set 红灯 车等着

import threading,time
import random
def light():
if not event.isSet():
event.set() #wait就不阻塞 绿灯状态 车走
count = 0
while True:
if count <10:
print("\033[42;1m--green light on--\033[0m") #绿灯10秒
elif count <13:
print("\033[43;1m--yellow light on--\033[0m") #黄灯3秒
elif count <20:
if event.isSet():
event.clear() #3#清除set 就是红灯 车等着
print("\033[41;1m--red light on--\033[0m") #红灯7秒
else:
count = 0
event.set() #打开绿灯
time.sleep(1)
count+=1
def car(n):
while 1:
time.sleep(random.randrange(10))
if event.isSet(): #绿灯
print("car [%s] is running..." % n)
else: #红灯
print("car [%s] is waiting"% n)

if __name__ == '__main__':
event = threading.Event() #定义事件
Light = threading.Thread(target=light) #创建一个灯的线程
Light.start()
for i in range(3): #创建3个车的线程
t = threading.Thread(target=car,args=(i,))
t.start()
 

















 


























posted @ 2016-03-06 18:55  王同佩  阅读(170)  评论(0)    收藏  举报