标签:显示 添加 UNC length 实例 raise utf-8 __new__ 反向
# ###
"""面向对象""" # ### self的意思就是当前类的(实例化)对象,cls的意思就是当前类 # (1)调用类中的属性或方法,对象obj.属性,obj.方法; 类(不带括号).属性,类.方法 类中方法括号里加了self,适合用对象调用(自动传参obj),如果用类调用就得在类的括号里加obj,类.func(obj) 类中方法括号里没有self,适合用类调用,类.func(),如果用对象调用就得将方法和对象绑定 在类当中调用类本身的属性或方法只能用 类.成员(能用类.成员吗) 或 self.成员 给类添加属性或方法,类.属性=xx 类.func=func(这个func自定义) 给对象添加属性或方法,对象.属性=xx 对象.func=func(这个func自定义) 类的命名一般用驼峰命名法 # MethodType 把自定义的方法绑定到对象上, types.MethodType(方法名,obj),再调用时用obj.方法名(不用传参obj) """import types""" # __dict__ 查看类或对象的成员,类.__dict__ 或 obj.__dict__ # _类名__私有成员名 利用改名策略调用私有成员(不推荐) 可通过在类中定义一个公有绑定方法,调用自己的私有成员,然后再在类外调用这个公有绑定方法 # object 是所有类的父类 # supper 本身是一个类,>>> supper()是一个对象,用于调用且只能调用父类的绑定方法 super().__init__() #必须继承父类的__init__构造方法 """self 与 super 的区别""" self 在调用父类成员时,如果自己本类含有该成员,调用自己的,否则调用父类的 super 永远只调用父类成员,不调用自己本类的 # mro列表:方法调用顺序列表 语法: 类.mro() 使用C3算法计算,返回一个列表 super() 就是按照这个列表的顺序,依次进行调用 # issubclass 判断是否是子父关系,和isinstance用法相似 类的成员属性和对象的成员属性不一样,存储在不同的内存空间 """魔术方法:特定时机自动触发""" # __init__ 构造方法,实例化对象时触发,能为对象添加新成员,参数self # __new__魔术方法,实例化对象时触发(触发时机在__init__之前),用来控制对象的创建过程, 参数(至少一个cls接收当前的类),通常返回对象或None """注意:__new__和__init__的参数要保持一致,除了一个是cls一个是self""" 如果__new__返回的不是自己本类的对象,不会触发构造方法__init__ class MyClass(): def __new__(cls): print(cls) #<class ‘__main__.MyClass‘> #借助父类objec,里面的__new__魔术方法创建对象 # 1 返回本对象 # return object.__new__(cls) # return obj 错误写法 # 2 返回其他类的对象 return obj2 #你实例化对象是别人的对象,然后对象.成员是别人的成员,别人没这个成员就报错 # 3 不返回任何对象 # return None #这样你实例化对象也相当于没这个对象,不能用对象了 """单态模式(单例模式):无论实例化对象多少次,都有且只有一个对象"""为了节省空间,加快效率,提出单态模式 (1)基本语法 class Singleton(): __obj = None def __new__(cls): if cls.obj is None: cls.obj = object.__new__(cls) return cls.__obj # __del__ 析构方法,当对象被内存收回时触发(1) 页面执行完毕回收所有变量, (2) 指向对象的变量名(obj1啊,obj2啊)都被删除),参数self,无返回值 # __call__魔术方法,把对象当作函数调用时触发,即obj()触发,用作模拟函数化操作,参数至少一个self,返回值看需求 # __str__魔术方法,用print(obj)或者str(obj)时触发,用来查看对象,参数self,必须返回字符串类型 # __repr__魔术方法,用repr(obj)时触发,用来查看对象,必须返回字符串类型 在系统底层默认加了 __str__=__repr__ ,所以用str(对象)的时候也可以触发 # __bool__魔术方法,用bool(对象)时触发,用来强转对象,参数self,必须返回bool型 # __add__魔术方法(与之相关的__radd__反向加法),obj+xx时触发__add__; xx+obj时触发__radd__,obj1+obj2时先触发__add__ # __len__魔术方法,用len(obj)时触发,用来检测对象或类中成员个数,参数self,必须返回整型 def __len__(self): return len([i for i in dictvar if not (i.startswith("__") and i.endswith("__"))]) <<<<<<<<<<<<<<<<重要知识点>>>>>>>>>>>>>> """见证奇迹: 1实例化对象并传参; 2将这个对象obj写入文档; 3运行完代码后关闭程序; 4打开代码把之前的实例化和写入文档注释掉,添加从文档中读取对象obj, 然后这个上次存入文档的对象还可以点出原来类MyClass以及对象的方法和属性 也就是说,在MyClass类不变的前提下把对象存进文档再拿出来他还是以前那个对象, 可以大大简化数据存储(以前要存多个变量,现在只用存一个对象就行了)""" import pickle class MyClass(): def __init__(self,name,age): self.name=name self.age=age def func(self): print("见证奇迹的时刻!") # obj=MyClass("狗子",10) # with open("test1.txt",mode="wb") as fp: # pickle.dump(obj,fp) with open("test1.txt",mode="rb") as fp: obj=pickle.load(fp) print(obj) print(obj.name) obj.func() """闭包函数""" 内函数调引外函数的变量称为闭包 def func(): name = ‘python‘ def inner(): print(name) print(inner.__closure__) return inner f = func() # f = func() = inner f() # f() = inner # 输出结果:python """装饰器""" # 是一种特殊的闭包函数 # 这里内函数就是引用了外函数的传参func,也称为闭包 定义:装饰用于拓展原来函数功能的一种语法,返回新函数替换旧函数 优点:在不更改原函数代码的前提下,给函数拓展新的功能 语法:@ ###1 装饰器的原型 def kuozhan(func): def newfunc(): print("厕所前蓬头垢面") func() print("厕所后容光焕发") return newfunc def func(): print("我是高富帅") func=kuozhan(func) #func=newfunc func() #调用newfunc # ###2 装饰器@符语法 #下面是基于python2.7的语法 # coding=utf-8 def func1(t_func): print "执行func1函数" print "打印传参的函数名", t_func.__name__ return "返回值" # func2=func1(func2) 也就相当于执行了func1函数传参func2,然后把结果赋值给func2了 @func1 def func2(): print "执行func2函数" print func2,type(func2) """ # 执行结果: 执行func1函数 打印传参的函数名 func2 返回值 <type ‘str‘> """ # self代表类的对象,一般用obj表示,传进去的也是这个对象 # cls代表类,一般在类中为别的类添加成员,需要带参数cls,然后cls.方法,cls.属性 """类中的方法:""" 无参的普通方法 : 只能用类调用 (1)绑定到对象(参数有self就是绑定到对象): 在调用当前方法时,自动传递self对象参数 (2)@classmethod 绑定到类(参数有cls): 在调用当前方法时,自动传递cls这个类参数 (3)@staticmethod 静态方法(一般没self,但可以有其他参数): 无论是对象还是类都 可以调用,把方法作为普通方法进行使用,有几个参数就传递几个参数 # property 把方法变成属性:用来控制成员的 获取 , 设置 , 删除 # 写法一 # @property下面跟(修饰)一个方法A 给一个方法添加property标志 # @方法A.setter下面跟一个方法B 设置这个property标志的方法A时,触发方法B #设置就是指更改 # @方法A.deleter下面跟一个方法C 删除这个property标志的方法A时,触发方法C # 写法二 先在类中定义def get_A(self) def set_A(self) def del_A(self) # 然后在类中写一行 username = property(get_A,set_A,del_A) 必须按照这个顺序进行传递:(获取方法 , 设置方法 , 删除方法),且只能传这3个参数 """正则表达式""" import re # re.findall 匹配所有内容,缺陷:不能把匹配到的内容和分组里面的内容同时显示出来,返回的是列表 lst = re.findall(正则表达式,字符串) # ###(1) 预定义字符集 # \d 匹配数字 # \D 匹配非数字 # \w 匹配字母或数字或下划线 (正则函数中,支持中文的匹配) # \W 匹配非字母或数字或下划线 # \s 匹配任意的空白符 \n \t \r " " # \S 匹配任意非空白符 # \n 匹配一个换行符 [最好在正则表达式的前面加上r,让转义字符失效,原型化匹配] # \t 匹配一个制表符 # ### (2) 字符组 从小组中默认选一个 # [123]从1,2,3中任选一个 # 0-9 0到9 -是特殊字符 , 具有特殊含义 # ^ 出现在字符组中,代表除了xx以外 # 匹配特殊符号 利用\ 让原来有意义的字符失效, 通过转义来实现匹配 # 匹配\ 用\\ # ###(1) 量词基本语法 # . 匹配除换行符以外的所有字符 # ? 匹配0个或者1个a # + 匹配1个或者多个a # * 匹配0个或者多个a # {m,n} 匹配m个至n个a,n可以取到 # {m,} 至少m次 # {m} 必须是m次 # ###(2)贪婪模式与非贪婪模式 贪婪模式:默认向更多次匹配, 非贪婪模式:默认向更少次匹配,在普通的匹配后面加 ? 如.?? .+? .*? .{1,25}? # ###(3) 边界符 # \bw 卡住左边界(就是匹配以\bw右边字符为开头的字符) # d\b 卡住右边界(就是匹配以d\b左边字符为结尾的字符) # ^ 整个字符串必须以...开头 # $ 整个字符串必须以...结尾 如果正则表达式里面出现了^ $ ,代表把这个字符串看成一个整体,再去匹配 # ###匹配分组 # (xxx) 把想要匹配的内容,用小圆括号包起来,表达分组,并且优先显示括号内的东西(优先显示就是只显示它) # (?:xxx) ?: 取消括号优先显示的功能 # | 代表或 , a|b 匹配字符a 或者 匹配字符b . 把用来匹配长字符串的写在前面, 用来匹配短字符串的写在后面,不然会匹配不到那个长的字符串 # \ 可以把有意义的字符变得无意义,还可以把无意义的字符变得有意义,用来转义字符 # r"\d+\.\d+|\d+"匹配小数和整数,优化写法 r"\d+(?:\.\d+)?" # search 匹配到一个内容就直接返回,优点:可以把分组的内容,和实际匹配到的内容分开,同时显示,返回的是对象obj # obj.group() 获取匹配到的内容,返回字符串 # obj.groups() 获取分组里面所有的内容,返回元组 # ###命名分组 # \1 反向引用,代表的是把第一个括号匹配到的值,拿过来在引用一次r"<(.*?)>(.*?)<(/\1)>" # (?P<组名>正则表达式) 给这个组起一个名字 (?P=组名) 引用之前组的名字,把该组名匹配到的内容放到当前位置 "<p>今天天气不错</p>" lst = re.findall(r"<(?P<tag1>.*?)>(.*?)</(?P=tag1)>",strvar) """正则函数""" # match 验证用户输入内容 search在正则表达式的前面加上^ 就与match函数一模一样 # re.split 语法 re.split("正则表达式",字符串,分割的次数-可选) 按正则表达式选出的字符串分割,返回列表? # sub 替换 返回的结果是一个字符串re.sub(r"[|&-]","%",strvar) """注意,如果正则表达式里面带括号,sub不会只替换括号里的内容,所以需要把除括号以外的字符串都加上 例如a=re.sub("下载(.*?)漫(.*?)的","678",b)会直接把 下载(.*?)漫(.*?)的 这一段替换成678 所以要用a=re.sub("下载(.*?)漫(.*?)的","下载"+"678"+"漫画里的",b) """ # subn 替换 用法上与sub一样,但是返回的结果是元组(替换后的结果,替换的次数) # finditer 匹配字符串中相应内容,返回迭代器(装着对象的迭代器) findall 与 finditer用法一样,区别在于 findall返回的是列表,finditer返回迭代器 # compile 指定一个统一的匹配规则,用compile 编译一个正则表达式,终身受益,不用对同一个正则反复编译啦 pattern = re.compile("\d")编译; res = pattern.findall(strvar)使用 # ### 修饰符 # re.I 使匹配对大小写不敏感 ("<h1>(.*?)</h1>",字符串,flags=re.I) # re.M 使每一行都能够单独匹配(多行匹配),影响 ^ 和 $ ,就是把每一行都当成一个字符串取匹配 # re.S 使 . 匹配包括换行在内的所有字符(有换行的话匹配出来还有\n) # flags=re.I|re.S 使用多个修饰符的写法 (拓展) #修饰符之间用|分割 """与类相关的魔术属性""" # __doc__ 获取对象或类的内部文档 用法 对象/类.__doc__ # __name__ 获取类名函数名 # __class__ 获取当前对象所属的类 # __bases__ 获取一个类直接继承的所有父类,返回元组 """类中的反射""" 通过对象名/类名/文件名(都是字符串) 获取对应对象/类/文件中的成员 # hasattr() 检测对象/类中是否有指定的成员 hasattr(obj,"eat") 记法(has attribute),返回Ture/False # getattr() 获取对象/类成员的值 获取属性就返回值,获取方法就返回函数,这个函数可以直接调用 res = getattr(obj,"eye") print(res)通过对象把属性返回出来 func = getattr(obj,"eat")对象反射调用func(); func = getattr(Children,"eat")类反射调用func() """新用法:getattr可以从模块里获取模块中的类或者模块中的函数,getattr(模块,类名或函数名),返回类或函数""" # ###通过对象把方法反射出来,是绑定方法 #绑定方法调用不用传参,通过类把方法反射出来,是普通方法 #普通方法需要传参 # res = getattr(Children,"abc","对不起,没有该成员")# 可以为getattr设置默认值, 如果找不到该成员,在第三个参数上可以设置相应的返回值 class Test1(): bbb=111 def myfunc(self): print("类中的方法") obj=Test1() getattr(Test1,"myfunc")(obj) print(getattr(Test1,"bbb")) # setattr() 设置对象/类成员的值 # 设置对象成员属性setattr(obj,"hair","天蓝色的"),设置类的成员方法setattr(Children,"age",func) 其中func自己定义 当然你可以用obj.hair = "天蓝色的"设置对象的属性,但是你知道的是字符串"hair",就需要用setattr了 # delattr() 删除对象/类成员的值 ##### (2)模块的反射##### import sys # sys.modules 返回一个系统字典,字典的键是加载的所有模块 print(sys.modules["__main__"])找到此文件的模块(类,方法和属性) #####异常处理##### # IndexError 索引超出序列的范围 # KeyError 字典中查找一个不存在的关键字 # NameError 尝试访问一个不存在的变量 # IndentationError 缩进错误 # AttributeError 尝试访问未知的对象属性 # StopIteration 迭代器没有更多的值 # AssertionError 断言语句(assert)失败, assert 5>3 #对,不报错;assert 5<2 #错,报错 try: #把可能存在问题的代码放到try这个代码块之后, code1 #如果没有异常,就不走except except: code2 #如果出现异常直接执行except这个代码块里面内容 # except后可以跟系统错误类型名,若是这种错误类型,则执行这条语句 except IndexError: print("我是IndexError错误类") except KeyError: print("我是KeyError错误类") except: print("有异常错误") # try ... finally 如果有报错,报错让你报,不管有没有错finally中的代码块都要执行 # try ... except ... else 如果不报错就走else分支,报错了就不执行else,不执行except, finally 和 else 不能够同时存在 # for/while ... else ... (了解) 如果循环异常终止(break,或者在函数中通过return终止的),不走else分支 # raise 主动抛出异常,BaseException是所有异常类的父类(基类,超类); Exception是所有普通异常类的父类(基类,超类) try: raise BaseException except BaseException: pass # raise 后面如果什么也不写 , 默认抛出的是BaseException try: print(a) except BaseException as b: print(666666) print(b)) # 拓展 try: print("待检测代码") except: print("try代码块出错走这里") else: print("try代码块成功走这里") finally: print("try代码块成功与否都走这里") """网络编程""" 子网掩码和ip地址相与,得到网段,相同网段的两个主机才能够传输数据,子网掩码和ip都可以自己设置 # 子网掩码: 255.255.255.0 => 11111111.11111111.11111111.00000000 # ip1: 192.168.10.12 => 11000000.10101000.00001010.00001100 # 子网掩码 & ip1 11000000.10101000.00001010.00000000 得到网段1:192.168.10.0 # ip2: 192.168.1.16 => 11000000.10101000.00000001.00010000 # 子网掩码 & ip2 11000000.10101000.00000001.00000000 得到网段2:192.168.1.0 # 网段不同,不能互相通信 # 子网掩码2: 255.255.0.0 # ip1 192.168.10.12 得到网段1:192.168.0.0 # ip2 192.168.1.16 得到网段2:192.168.0.0 # 网段相同,可以互相通信 # 常用端口 # IIS(HTTP):80 # MySQL:3306 # FTP:21 # SSH:22 """socket""" 一发一收是一对send,recv必须在个数上保持一致,否则收发次数不匹配,会出现异常 # ###tcp基本语法 server 服务端 import socket sk=socket.socket() #1 创建一个socket实例化对象 sk.bind(("10.0.3.160",8000)) #2 绑定ip和端口(用元组表示)(在网络上注册该主机) sk.listen() #3 开启监听 conn,addr=sk.accept() #4 建立三次握手 其中conn是三次握手成功之后的连接对象,addr是对方ip和端口 msg=conn.recv(1024) #5 接收数据 print(msg.decode("utf-8")) #将字节流解码成文字后打印 conn.send("戏说".encode="utf-8") # 发送数据 (将文字编码成二进制字节流) conn.close() #6 四次挥手 sk.close() #7 退还端口 # ###tcp基本语法 client 客户端 import socket sk=socket.socket() #1 创建一个socket对象 sk.connect(("10.0.3.160",8000)) #2 连接此ip和端口的服务器 sk.send("不谓侠".encode("utf-8")) #3 发送数据 msg=sk.recv(1024) #接收数据 print(msg.decode("utf-8")) #解码打印 sk.close() #4 退还端口 ########## sk.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1) 在测试阶段,可以用这个支持端口复用 # ### tcp 循环发消息 server端 import socket sk = socket.socket() sk.bind( ("127.0.0.1",9003) ) sk.listen() while True: conn,addr = sk.accept() while True: res = conn.recv(1024) print(res.decode()) strvar = input("请输入你要给对方的消息:") conn.send(strvar.encode()) if strvar == "q": break conn.close() #断开一个client端,其他端还连着 sk.close() # ### tcp循环发消息 client端 import socket sk = socket.socket() sk.connect( ("127.0.0.1",9003) ) while True: strvar = input("请输入您要发送的消息:") sk.send(strvar.encode()) res = sk.recv(1024) if res == b"q": break print(res.decode()) sk.close() # ### udp 服务端 import socket sk=socket.socket(type=socket.SOCK_DGRAM) #1.创建一个socket对象,括号里的参数代表使用udp连接 sk.bind(("127.0.0.1",9000)) # 2.绑定ip,端口号 # 3.收发数据 """udp协议,如果作为服务器,第一次需要先接受消息,才能得到对方的ip和端口号""" msg,cli_addr = sk.recvfrom(1024) print(msg.decode(),cli_addr) msg = "iG牛逼" sk.sendto(msg.encode("utf-8"),cli_addr) sk.close() # 4.关闭连接 # ### 客户端 import socket sk = socket.socket(type=socket.SOCK_DGRAM) # 1.创建socket对象 msg = "s9总决赛,lpl再造辉煌,凤凰涅槃" # 2.发送消息 sk.sendto(msg.encode("utf-8"),("127.0.0.1",9000)) # sendto(发送的二进制字节流消息,对方的ip和端口[元组]) msg,addr = sk.recvfrom(1024)# 接受数据 print(msg.decode("utf-8"),addr) sk.close# 3.关闭udp连接 # udp 默认允许多人同时会话,并且不会黏包 # tcp 默认不允许,只能等当前用户4次挥手之后,才能建立新的链接;可能会黏包 """struct模块""" import struct """pack和unpack的应用""" length=len("小祖宗我爱你") res=struct.pack("i",length) # 把任意长度的整型("i"指代整型)数字转化成具有4个字节固定长度的字节流 tup = struct.unpack("i",res) # 把4个字节值恢复成原本的整型("i"指代整型)数字,返回的是元组 print(tup[0]) #6 """hashlib 模块 加密算法""" import hashlib # ###基本语法 hs=hashlib.md5(strvar1.encode("utf-8")) #(1)创建一个md5算法对象,括号里也可不带参数,之后再update补上也行 hs.update(strvar2.encode()) #(2)把要加密的字符串通过update更新到hs这个对象当中进行运算 res=hs.hexdigest() #(3)得到加密后的32位字符串 数据类型需要:二进制字节流 # 常见的加密算法 安全性: hmac > (sha1 sha512) > md5,其中后三个用法相同 # ### hmac import hmac """可以直接在英文或数字前加b转成字节流""" hm=hmac.new(strvar1,strvar2) #参数可以只带一个,就加密一个 hm.update("777".encode()) #也可以update res=hm.hexdigest() #得到加密后的字符串 """os.urandom(n) 返还长度为 n的随机二进制字节流""" """进程""" from multiprocessing import Process # os.getpid() 获取当前进程号 # os.getppid() 获取当前父进程号 def func(n): for i in range(1,n+1): print("1子进程号>>>%s , 2父进程号>>>%s"%(os.getpid(),os.getppid())) if __name__=="__main__": n=5 p=Process(target=func,args=(n,)) p.start() for i in range(1,6): print("*"*i) print("3子进程号>>>%s , 4父进程号>>>%s"%(os.getpid(),os.getppid())) # p.join() 等待进程,等待标记的子进程执行完毕后,再执行下方语句, 主进程(或别的子进程)的任务再继续执行,保证子父进程的同步性 # daemon 守护进程 (陪葬进程) 语法 p.daemon=True """ 默认情况下,主进程要等待所有子进程执行完毕之后,才会关闭程序,释放资源 守护进程进行在主进程代码执行结束之后,就直接关闭; 守护进程守护的是主进程 必须要写在start()调用之前,进行设置 """ # lock (互斥锁) 用于多进程中,开进程调用函数时需要传参lock给上锁, 上锁解锁是一对一对的,进程间谁先抢到资源谁就先上锁, from multiprocessing import Process,Lock """with lock: #上锁写法二""" # 解锁后下一个进程再继续使用,上锁的时候是同步过程,其他时候是异步 # lock.acquire()上锁 lock.release()解锁 from multiprocessing import Process,Lock # Semaphore 信号量,本质上就是锁,同一时间可以上多把锁 sem=Semaphore(3) 同一时 间可上3把锁,sem.acquire()上锁,sem.release()解锁 from multiprocessing import Process,Semaphore # Event 事件 # 阻塞事件:e=Event()生成事件对象e , e.wait()动态给程序加阻塞 , from multiprocessing import Process,Event # 程序当中是否加阻塞完全取决于该对象中的 is_set() [默认返回值是False] # 如果是True 不加阻塞,如果是False 加阻塞 # set()方法:将这个属性的值改成True, clear()方法:将这个属性的值改成False # is_set()方法 判断当前的属性是否为True (默认上来是False) # Queue 进程队列,先进先出 (让进程之间共享队列资源),q=Queue()实例化对象, 括号里可加参数指定队列长度n,放值q.put("狗子"),取值res=q.get() from multiprocessing import Process,Queue get_nowait()在没值的时候,直接报错; put_nowait(243) 如果超出了队列长度,直接报错 # JoinableQueue 和普通的Queue队列的不同点是前者可以在队列中元素个数为0时放行,队列中有元素时可以加阻塞 from multiprocessing import Process,JoinableQueue jq=JoinableQueue()实例化,jq.put(xx)存放,jq.get()获取, jq.task_done()队列元素计数减一(需要手动减),jq.join() 阻塞 # Manager list dict 能够实现进程之间的数据共享,为了保证数据的准确性,必要时加锁 from multiprocessing import Process,Manager,Lock #调用函数时需要传参list # Pool 进程池 (旧版进程池,没法传参???) from multiprocessing import Process,Pool ...... listvar=[] p1=Pool(6) #创建进程池对象 for i in range(10): res=p1.apply_async(func) #异步开启进程池,res应该是进程池函数 listvar.append(res) for i in listvar: print(i.get()) #获取并打印执行函数的返回值,若只开一个进程池,直接res.get()获取到 p1.close() #close和join要一起用,让主进程等待进程池执行完再执行 p1.join() res=os.cpu_count() #获取cpu的核心数(逻辑处理器的数量) Process : 属于异步并发程序,主进程会默认等待子进程全部执行完毕之后,在终止程序 Pool : 属于异步并行程序,在没有任何阻塞的情况下,只要主进程执行完毕,会立刻终止所有子进程; p = Pool(6)实例化对进程池对象,代表同一时间最多允许并行6个进程,不写参数就默认开辟逻辑处理器数量个进程 在进程池中,如果一个进程执行任务的速度太快,会包揽更多的任务执行,就不会创建新的进程; res=p1.apply_async(func)异步开启进程池, res=p.apply(func)同步开启进程池,可用res.get()接收到任务的返回值 """线程""" Thread 线程速度比进程速度快,进程中可以包括多个线程,多线程共享同一份进程资源 from threading import Thread,currentThread t=Thread(target=func) t.is_alive()检测线程是否仍然存在, t.setName()设置线程名字,t.getName()获取线程名字,currentThread().ident查看线程id号, enumerate()返回目前正在运行的线程列表,activeCount()返回目前正在运行的线程数量 # setDaemon 守护线程,等待所有线程执行结束后再终止,守护所有线程,t1.setDaemon(True), 注意,和Process子进程写法不一样 # Semaphore 信号量,和进程的信号量相同,可以同时上多把锁 """死锁,递归锁,互斥锁""" # rlock 递归锁 语法 rlock = RLock(),直接用递归锁代替普通的锁,就可以解决死锁 from threading import RLock # 死锁: 连续上锁,不解锁,在windows里会发生死锁,阻塞运行 # 递归锁专门用来解决死锁现象,为了应急,临时解决线上死锁问题,使之正常运行; # local 线程之间的数据隔离,loc = local()创建对象,loc.val=666,这个数据就是隔离的 from threading import Thread,local,currentThread 普通数据在线程里是互通的,引入local, local.变量 就是隔离的 # Event 线程事件,和进程用法一样 # from threading import Event,Thread # Queue 线程队列,和进程队列用法相同,队列中一般只能插同一种数据类型,不能混合插入 # LifoQueue 栈队列,后进先出,模拟栈这个数据结构特点,用法同上,只是取得值的顺序不同 # PriorityQueue 排序队列,按照优先级顺序(比如数的大小,字母的大小)进行排序(默认从小到大排序) """改良版进程池_线程池""" # 新版进程池默认主进程在等待所有子进程执行结束之后,在终止程序,释放资源 from concurrent.futures import ProcessPoolExecutor,ThreadPoolExecutor # ProcessPoolExecutor 新版进程池 if __name__ == "__main__": (1) 创建进程池对象 ProcessPoolExecutor <==> Pool,括号里面可跟参数开辟多少个进程池 p = ProcessPoolExecutor() (2) 提交异步任务 submit <==> apply_async 还有也不用写 target= 和 args= 了 res = p.submit(func,66) #res应该是进程池函数,可以传参 print(res) (3) 获取返回值 result <==> get 内部也存在阻塞 res = res.result() print(res) (4) shutdown <==> close + join等待进程 p.shutdown() print("主进程执行结束 ... ") # ThreadPoolExecutor 新版线程池,用法和新版进程池相同 # map 高阶函数,返回迭代器 tp = ThreadPoolExecutor(5) it = tp.map(func,range(20)) #开20个线程池执行函数 """回调函数""" 把函数当成参数传递给另外一个函数 在当前函数执行完毕之后,调用一下传递进来的函数,该函数是回调函数 (1)add_done_callback 在获取当前线程的返回值的时候,可以异步并发,加快速度 (2)线程池的回调函数由当前子线程执行,进程池的回调函数由主进程执行 def func(): print("===func===") return "***" def call_back(obj): #obj这个参数必须传,用不用自己看 print(obj.result(),"===回调函数===") tp = ThreadPoolExecutor(5) #开启5个进程池执行一个func任务 obj = tp.submit(func) obj.add_done_callback(call_back) #使用回调函数,异步并发,注意名字固定不可改 tp.shutdown() print("主线程执行完毕"obj.result()) # 用进程池的写法也是一样 """协程"""线程是执行任务的主体,协程是给线程分配任务的,可分配多个任务,然后遇到阻塞就跳 # switch 遇到阻塞,可手动调用函数切换任务,缺点是不能自动规避阻塞io from greenlet import greenlet resquests gevent安装一下 => g1=greenlet(func1) ; g2=greenlet(func2) 创建两个协程对象 g1.switch() #开启switch协程的方式,跳转(切换)也是用这条语句 先运行g1,在可能会有阻塞的语句前加一个g2.switch()直接跳到g2执行 其实是遇到switch就跳,不管后面有没有阻塞,所以要靠人分辨会不会有阻塞,比较傻,看需求使用 # spawn 类似于switch,创建进程并且开始执行,遇到阻塞可以自动切换任务执行,默认在主线程执行结束时 # 终止一切协程任务(所以一般要加join),缺陷是不能识别部分阻塞,比如time.sleep() import gevent """将time.sleep()替换成gevent.sleep()就能识别了""" => g1=gevent.spawn(func1) ; g2=gevent.spawn(func2) 创建两个协程对象并且开始执行 注意加 g1.join()和g2.join() # monkey 可自动切换,并且能够识别各种阻塞 from gevent import monkey monkey.patch_all() #可以把下面引入的所有模块中的阻塞识别出来 import time import gevent ...... g1=gevent.spawn(func1) #创建并开始执行任务,不用另外的开启协程语句 (1)gevent.spawn(函数,参数1,参数2...)启动一个协程任务 (2)joinall([协程列表]) 等待所有协程任务执行完再往下执行 (3)value获取协程任务中的返回值g1.value或g2.value
标签:显示 添加 UNC length 实例 raise utf-8 __new__ 反向
原文地址:https://www.cnblogs.com/banbosuiyue/p/13773106.html