python:常用模块 知识整理
time模块
time.time() # 时间戳:1487130156.419527
time.strftime("%Y-%m-%d %X") #格式化的时间字符串:'2017-02-15 11:40:53'
time.localtime() #本地时区的struct_time
time.gmtime() #UTC时区的struct_time
时间戳 与 struct_time对象的相互转换
time.localtime(1473525444.037215) #时间戳到struct_time对象
time.mktime(time.localtime()) #struct_time对象到时间戳
时间字符串 与 struct_time对象的相互转换
time.strptime('2007-12-1 2-3-4','%Y-%m-%d %H-%M-%S') #字符串到struct_time对象
time.strftime("%Y-%m-%d %X", time.localtime()) #struct_time 到字符串
datetime模块
这个应该更强大的time模块
datetime.date 代表年月日,datetime.time代表时分秒,datetime.datetime代表年月日时分秒
时间加减
a = datetime.datetime.now()
datetime.datetime.now()-a > datetime.timedelta(days=30)
三者都具有差不多的函数。主要功能
datetime.datetime.fromtimestamp(time.time()) #1)时间戳到datetime.datetime对象
datetime.timedelta:datetime.datetime.now() + datetime.timedelta(hours=3) #2)时间加减对象,当前时间+3小时
datetime.datetime.now().replace(minute=3,hour=2). #3)时间替换
sys模块
sys.path.append
sys.stdout sys.stderr sys.stdin 三流
sys.modules[__name__] 获得本模块
random模块
random.random() #(0,1)----float 大于0且小于1之间的小数
random.randint(1,3) #[1,3] 大于等于1且小于等于3之间的整数
random.randrange(1,3) #[1,3) 大于等于1且小于3之间的整数
random.choice([1,'',[4,5]])#1或者23或者[4,5]
random.sample([1,'',[4,5]],2)#列表元素任意2个组合
random.uniform(1,3) #大于1小于3的小数,如1.927109612082716
item=[1,3,5,7,9]
random.shuffle(item) #打乱item的顺序,相当于"洗牌"
os模块
os模块是与操作系统交互的一个接口
os.urandom(32) #获得32字节的随机数,字节类型
os.getcwd() #获取当前工作目录,即当前python脚本工作的目录路径
os.chdir("dirname") # 改变当前脚本工作目录;相当于shell下cd
os.makedirs('dirname1/dirname2') #可生成多层递归目录
os.removedirs('dirname1') # 若目录为空,则删除,并递归到下一级目录,如若也为空,则删除,依此类推
os.mkdir('dirname') # 生成单级目录;相当于shell中mkdir dirname
os.rmdir('dirname') # 删除单级空目录,若目录不为空则无法删除,报错;相当于shell中rmdir dirname
os.listdir('dirname') # 列出指定目录下的所有文件和子目录,包括隐藏文件,并以列表方式打印
os.remove(‘filepath’) # 删除一个文件
os.rename("oldname","newname") # 重命名文件/目录
os.stat('path/filename') # 获取文件/目录信息
os.name #输出字符串指示当前使用平台。win->'nt'; Linux->'posix'
os.system("bash command") # 运行shell命令,直接显示
os.path.abspath(path) # 返回path规范化的绝对路径
os.path.split(path) # 将path分割成目录和文件名二元组返回
os.path.dirname(path) # 返回path的目录。其实就是os.path.split(path)的第一个元素
os.path.basename(path) # 返回path最后的文件名。若path以/或\结尾,那么就会返回空值。即os.path.split(path)的第二个元素
os.path.exists(path) # 如果path存在,返回True;如果path不存在,返回False
os.path.isabs(path) # 如果path是绝对路径,返回True
os.path.isfile(path) # 如果path是一个存在的文件,返回True。否则返回False
os.path.isdir(path) # 如果path是一个存在的目录,则返回True。否则返回False
os.path.join(path1[, path2[, ...]]) # 将多个路径组合后返回,第一个绝对路径之前的参数将被忽略
os.path.getatime(path) # 返回path所指向的文件或者目录的最后存取时间
os.path.getmtime(path) # 返回path所指向的文件或者目录的最后修改时间
os.path.getsize(path) #返回path的大小
注意:os.path.getsize() 和 f.seek(0,2) f.tell() 和os.stat(path).st_size 的结果相同
os.walk('dir_path') # 详细用法。os.walk()常用于获取非执行目录的绝对路径,os.path.abspath(),只是将文件名加上当前目录路径
如何获得一个路径下面所有的文件路径:
import os
path = r'C:\Users\Administrator\Desktop\file'
for dirpath,dirnames,filenames in os.walk(path):
for filename in filenames:
print(os.path.join(dirpath,filename))
optparse模块
比sys.argv更好的参数处理
op = optparse.OptionParser()
op.add_option('-s','--server',dest='server')
op.add_option('-p','--port',dest='port')
options, args = op.parse_args() #传入完成,做解析
注意:options不是字典 option['server']会报错,取值应该是options.server
外部传参例子:
python ftpserver.py -s 127.0.0.1 -p 8080
输出:
options: {'server':'127.0.0.1','port':'8080'}
args :[] #没有定义绑定的信息。
shutil模块
高级的 文件、文件夹、压缩包 处理模块
shutil.copyfileobj(open('old.xml','r'), open('new.xml', 'w')) #将文件内容拷贝到另一个文件中:
shutil.copyfile('f1.log', 'f2.log') #拷贝文件,目标文件无需存在
shutil.copymode('f1.log', 'f2.log') #拷贝权限。内容、组、用户均,不变目标文件必须存在
shutil.copystat('f1.log', 'f2.log') #拷贝状态的信息,包括:mode bits, atime, mtime, flag,s目标文件必须存在
shutil.copy('f1.log', 'f2.log') #拷贝文件和权限
shutil.copy2('f1.log', 'f2.log') #拷贝文件和状态信息
shutil.copytree('folder1', 'folder2', ignore=shutil.ignore_patterns('*.pyc', 'tmp*')) #递归的去拷贝文件夹:目标目录不能存在,注意对folder2目录父级目录要有可写权限,ignore的意思是排除
shutil.rmtree('folder1'),#删除非空文件夹
shutil.move('folder1', 'folder3') # 递归的去移动文件,它类似mv命令,其实就是重命名
ret = shutil.make_archive("/tmp/data_bak", 'gztar', root_dir='/data') #创建压缩包并返回文件路径,例如:zip、tar:
#将 /data下的文件打包放置 /tmp/目录
#pyhton中含有对解压操作的两个模块:zipfile,tarfile#
json模块、pickle模块
这两个类都序列化用
json强大在可以在任何语言的数据交换。不能传输类,只能传输基本类型
json.dumps(xx) #转化为json字符串、参数可以是字典、列表、元组、基本数据类型
json.loads(xx) #传入json字符串,还原为原来的数据,和eval不同的是,eval侧重于语句,eval('1+1')可以执行,json则可以跨语言,
-----------------------------------------------------------------------------------------
json.dumps(books, default=lambda o: o.__dict__) . # 将对象转化为对象内部的字典,有递归效果 --------------------------------------------------------------------------------------------
#扩展json序列化引擎类,序列化datetime对象
class CJsonEncoder(json.JSONEncoder):
def default(self, obj):
#if isinstance(obj, datetime):
#return obj.strftime('%Y-%m-%d %H:%M:%S')
if isinstance(obj, datetime.date):
return obj.strftime('%Y-%m-%d %H:%M:%S')
else:
return json.JSONEncoder.default(self, obj) import json
import datetime a = datetime.datetime.now()
print(a) b = json.dumps(a,cls=CJsonEncoder)
print(b)
附:django序列化(专门用于序列化django的models对象)
from django.core import serializers
ret = models.BookType.objects.all()
data = serializers.serialize("json", ret)
pickle只能在python与python之间的交换,但什么都可以支持,类,函数啊,函数只传递地址,不传递函数体,没多大意义
注意: 使用pickle模块,打开文件时需要'wb')模式,因为pickle.dumps(xx)#转化为字节
shelve模块
也是序列化模块,操作为{key:{}}形式
import shelve
f=shelve.open(r'sheve.txt')
f['stu1_info']={'name':'egon','age':18,'hobby':['piao','smoking','drinking']}
f['stu2_info']={'name':'gangdan','age':53}
f['school_info']={'website':'http://www.pypy.org','city':'beijing'}
print(f['stu1_info']['hobby'])
f.close()
hashlib模块
hashlib在3.x里代替了md5模块和sha模块,主要提供 SHA1, SHA224, SHA256, SHA384, SHA512 ,MD5 算法),该算法接受传入的内容,经过运算得到一串hash值
扩展:hash算法特点
1.加密不可逆
2.只要传入的内容一样,得到的hash值必然一样
3,只要使用的hash算法不变,无论校验的内容有多大,得到的hash值长度是固定的
普通用法:
m=hashlib.md5()
m.update('helloalvin'.encode('utf8')) #只能传入字节
m.hexdigest() #92a7e713c30abbb0319fa07da2a5c4af
注意:update内部有一个排他集合,会将所有分批传入的数据一起计算。所以如果要分开一个数据一个数据地加密,一定要重新初始化加密算法对象。
防止撞库,对加密算法中添加自定义key再来做加密:
hash = hashlib.sha256('898oaFs09f'.encode('utf8')) #添加自己的key,然后初始化
hash.update('alvin'.encode('utf8'))
hash.hexdigest()#e79e68f070cdedcfe63eaf1a2e92c83b4cfb1b5c6bc452d214c1b7e77cdfd1c7
base64模块
双向可解的加密
base64.b64encode(''.encode('utf8'))
#'MTIzNDU2'
base64.b64decode('MTIzNDU2'.encode('utf8'))
#'123456'
hmac
加入自定义秘钥生成唯一字节流
secret_key = b'qazwsx123'
msg = os.urandom(32)
h=hmac.new(secret_key,msg) #使用随机生成的msg对secret_key加密
digest=h.digest() #产生加密结果
hmac.compare_digest(digest,respone) #比较字节是否相等
configparser模块
操作配置文件。
配置文件的格式
[section1]
k1 = v1
k2:v2
user=egon
age=18
is_admin=true
salary=31
[section2]
k1 = v1
config = configparser.ConfigParser() #1.必须操作,创建对象
取值:
config.read('a.cfg') #像文件一样首先打开
res=config.sections() #查看所有的标题:['section1', 'section2']
options=config.options('section1') #查看标题section1下所key=value的key组成的列表:
val=config.get('section1','user') #取出指定section的指定键的值
#注意,get还有其他‘子类’函数,适用于取出特定类型,就是简化取出之后的类型转换步骤
写(改):
config.remove_section('section2') #删除整个节section2
config.remove_option('section1','k1') #删除节下面的指定键值对
config.add_section('egon') #添加一个标题:
config.set('egon','name','egon') #在标题egon下添加name=egon,age=18
config.write(open('a.cfg','a+')) #写入文件
判断
config.has_section('section1') #判断有指定节
config.has_option('section1','') #判断节下面是否有
用处:
1)程序调试
2)了解软件程序运行情况,是否正常
3)软件程序运行故障分析与问题定位
4)还可以用来做用户行为分析,如:分析用户的操作行为、类型洗好、地域分布以及其它更多的信息,由此可以实现改进业务、提高商业利益。
功能有设置输出日志的等级、日志保存路径、日志文件回滚等;
相比print,其可以通过设置不同的日志等级,在release版本中只输出重要信息,而不必显示大量的调试信息;
日志级别
默认级别为warning,默认打印到终端,低于级别的日志不输出
CRITICAL = 50 #FATAL = CRITICAL
ERROR = 40
WARNING = 30 #WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0 #不设置
配置
logging.basicConfig()函数中通过具体参数来更改logging模块默认行为。
#这是全局配置,针对所有logger有效
#并且这个配置比较低级, #常用两者之一,有stream参数就不能设置filename,反过来也是
logging.basicConfig(level=logging.DEBUG,stream=std.__stdout__)
logging.basicConfig(level=10,filename='log.log')
Formatter,Handler,Logger,Filter对象
logger:产生日志的对象
Filter:过滤日志的对象,一般不用
Handler:接收日志然后控制打印到不同的地方,FileHandler用来打印到文件中,StreamHandler用来打印到终端
Formatter对象:可以定制不同的日志格式对象,然后绑定给不同的Handler对象使用,以此来控制不同的Handler的日志格式 #1.logger对象:负责产生日志,然后交给Filter过滤,然后交给不同的Handler输出
logger=logging.getLogger(__file__) #2、Filter对象:不常用,略 #3、Handler对象:接收logger传来的日志,然后控制输出
h1=logging.FileHandler('t1.log') #打印到文件
h3=logging.StreamHandler() #打印到终端 #4、Formatter对象:日志格式
formmater1=logging.Formatter('%(asctime)s - %(name)s - %(levelname)s -%(module)s: %(message)s',datefmt='%Y-%m-%d %H:%M:%S %p',)
formmater3=logging.Formatter('%(name)s %(message)s',)
为Handler对象绑定格式
h1.setFormatter(formmater1)
h3.setFormatter(formmater3)
将Handler关联logger
logger.addHandler(h1)
logger.addHandler(h3)
设置等级
logger.setLevel(10) logger.debug('debug')
logger.info('info')
logger.warning('warning')
logger.error('error')
logger.critical('critical')
自定义的logger类,用于辅助其他类(self.logger=PluginLogger())
import logging
import os
from conf import setting class Log(object):
__instance = None def __init__(self):
self.error_log_path = setting.ERROR_LOG_PATH
self.run_log_path = setting.RUN_LOG_PATH
self.error_log = None
self.run_log = None
self.__init_error_log()
self.__init_error_log() def __new__(cls, *args, **kwargs):
if not cls.__instance:
cls.__instance = object.__new__(cls, *args, **kwargs)
return cls.__instance def __check_path_exists(self, file_path):
if not os.path.exists(file_path):
raise Exception('%s not exists' % file_path) def __init_error_log(self):
self.__check_path_exists(self.error_log_path)
logger = logging.Logger('error_log', logging.ERROR)
h = logging.FileHandler(self.error_log_path, 'a', encoding='utf8')
fmt = logging.Formatter(fmt="%(asctime)s - %(levelname)s : %(message)s")
h.setFormatter(fmt)
logger.addHandler(h)
self.error_log = logger def __init_run_log(self):
self.__check_path_exists(self.run_log_path)
logger = logging.Logger('run_log', logging.INFO)
h = logging.FileHandler(self.run_log_path, 'a', encoding='utf8')
fmt = logging.Formatter(fmt="%(asctime)s - %(levelname)s : %(message)s")
h.setFormatter(fmt)
logger.addHandler(h)
self.run_log = logger def log(self, msg, status=True):
if status:
self.run_log.info(msg)
else:
self.error_log.error(msg) logger = Log()
自定义配置
一般正规的开发,不会使用以上的对象进行配置。
logging标准模块支持三种配置方式: dictConfig,fileConfig,listen。其中,dictConfig是通过一个字典进行配置Logger,Handler,Filter,Formatter;fileConfig则是通过一个文件进行配置;而listen则监听一个网络端口,通过接收网络数据来进行配置。
了解logger的继承,用于filter对象
logger1=logging.getLogger('abc')
logger2=logging.getLogger('abc.freedom')
logger3=logging.getLogger('abc.freedom.child2')
通过父名.子名继承,名字自定义,继承后,父logger输出时,子对象也会输出一份相同的,但子对象也可以自己另外输出。
django的配置说明
'file': {
'level': 'INFO',
'class': 'logging.handlers.TimedRotatingFileHandler', # 用时间切割
'when': "D", #D 表示天
'interval': 1, #1 表示每1天,每天切割一次日志文件
"backupCount": 3,
'formatter': 'default',
'filename': os.path.join(BASE_DIR, 'logs', 'dbops.log')
},
re模块
正则表达式深入用法
1.sub将指定字母替换为大写,若使用lambda函数形式,记得传入的是匹配到的正则结构,要使用group提出
re.sub(r'(a)',lambda x:x.group(0).upper(),'caca')
2.使用|方式,要在()阔住,并且在阔号最前面加入?:
re.findall('compan(?:y|ies)','Too many companies have gone bankrupt, and the next one is my company')
3.正则函数一般有一个参数flags可以传入正则标志,例如忽略大小写,还有正则默认不匹配换行符,标志设置为re.S就适用于有换行的字 符串,注意的是换行符无需在正则里写出来
4.re.split,普通的字符串split只能按照一个传入的字符串匹配,但这个可按照多个
re.split('[ab]','abcd') #['', '', 'cd'],先按'a'分割得到''和'bcd',再对''和'bcd'分别按'b'分割
re.split('[ab]','acaccccbzzzafreedom')
['', 'c', 'cccc', 'zzz', 'freedom']
5.sub函数还有个count参数,指定替换多少次
re.sub('a','A','alex make love',1) Alex make love
6.re.compile可以实现正则的重用,并且速度快于用字符串保存的正则
obj=re.compile('\d{2}')
obj.search('abc123eeee').group()) #
obj.findall('abc123eeee')) #['12'],重用了obj
7.阔号后面配频率符,少用。因为各种re的函数的处理都不同
看这个例子:(\d)+相当于(\d)(\d)(\d)(\d)...,是一系列分组
print(re.search('(\d)+','').group()) #group的作用是将所有组拼接到一起显示出来
print(re.findall('(\d)+','')) #findall结果是组内的结果,且是最后一个组的结果
8.group(0)是返回匹配到的全部,group(1)开始就是返回正则表达式阔号的值。默认group()便是group(0)
9.注意,match,从第一个字母查找,满足所编写的正则后便返回。
re.match(r'ddd','ddd32')
<_sre.SRE_Match object; span=(0, 3), match='ddd'>
10.?:这个代表不捕获分组
比较(X)和(?:X),前者是捕获分组,后者不捕获,区别在于正则表达式匹配输入字符串之后所获得的匹配的(数)组当中没有(?:X)匹配的部分;
比如
注意:这个是javascript
var m = "abcabc".match(/(?:a)(b)(c)/)
结果 ["abc", "b", "c"] var m = "abcabc".match(/(a)(b)(c)/)
结果 ["abc", "a", "b", "c"]
11.正则如果有冲突的话,前面加上'\',而r前缀的作用是拟制\n \t之类的转义字符,与冲突字符无关
In [30]: re.match(r'www\.','www.')
Out[30]: <_sre.SRE_Match object; span=(0, 4), match='www.'>
12.正则的(?=rex),匹配指定正则的‘前面部分’的‘预扫描’
#预扫描就是先走一遍,找到?=中的正则,然后返回匹配的结果。剩下的正则,还是从‘预扫描’正则的前一个正则处理完的位置开始。
re.match(r'(?=123|456)(?=123abc)(?=123abcfree)123abcfree','123abcfree')
Out[]: <_sre.SRE_Match object; span=(, ), match='123abcfree'> #预匹配经常用于这样的场景,例如:密码需要包含大小写字母,数字和下划线
re.match(r'(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*_).*','fdfds2121_FSD')
Out[111]: <_sre.SRE_Match object; span=(0, 13), match='fdfds2121_FSD'>
uuid模块
用于生成唯一标志符
uuid1()——基于时间,由MAC地址、当前时间戳、随机数生成。可以保证全球范围内的唯一性
functools模块
Python装饰器(decorator)在实现的时候,被装饰后的函数其实已经是另外一个函数了(函数名等函数属性会发生改变),为了不影响,Python的functools包中提供了一个叫wraps的decorator来消除这样的副作用。写一个decorator的时候,最好在实现之前加上functools的wrap,它能保留原有函数的名称和docstring。
from functools import wraps
def hello(fn):
@wraps(fn)
def wrapper():
print "hello, %s" % fn.__name__
fn()
print "goodby, %s" % fn.__name__
return wrapper
subprocess模块
打开一个子进程执行shell
res=subprocess.Popen('dir',shell=True,stdout=subprocess.PIPE) #shell=True意味着用shell命令形式执行第一参数'dir',stdout参数指定将结果放到管道里面。
res.stdout.read() #从管道中读出数据,数据为二进制 res=subprocess.getoutput('ver') #直接获取cmd命令的返回值
常用做法:将输入流,输出流,错误流都定义到管道
res=subprocess.Popen('ls',shell=True,stdout=subprocess.PIPE,stdin=subprocess.PIPE,stderr=subprocess.PIPE) # 注意,虽说是这么写,但是其实是不同的管道。
struct模块
数据打包为二进制bytes的模块
例如,用使用四个字节表示2007这个数字。常用于拼接网络传输的应用层协议头
注意的是,因为常用于网路传输,网络传输后不是解码,还是调用unpack取出
a=struct.pack('b',-1)
struct.unpack('b',a) #返回的是元祖
xlrd模块
不是内置模块,请pip install xlrd
操作excel文件,xlsx等
data = xlrd.open_workbook('demo.xls') #打开excel
data.sheet_names() #查看文件中包含sheet的名称
#得到第一个工作表,或者通过索引顺序 或 工作表名称
table = data.sheets()[0]
table = data.sheet_by_index(0)
table = data.sheet_by_name(u'Sheet1')
#获取行数和列数
nrows = table.nrows
ncols = table.ncols
#获取整行和整列的值(数组)
table.row_values(i)
table.col_values(i)
#循环行,得到索引的列表
for rownum in range(table.nrows):
print table.row_values(rownum)
#单元格
cell_A1 = table.cell(0,0).value
cell_C4 = table.cell(2,3).value
#分别使用行列索引
cell_A1 = table.row(0)[0].value
cell_A2 = table.col(1)[0].value
socket模块
服务端套接字函数
s.bind() 绑定(主机,端口号)到套接字
s.listen() 开始TCP监听
s.accept() 被动接受TCP客户的连接,(阻塞式)等待连接的到来 客户端套接字函数
s.connect() 主动初始化TCP服务器连接
s.connect_ex() connect()函数的扩展版本,出错时返回出错码,而不是抛出异常 公共用途的套接字函数
s.recv() 接收TCP数据
s.send() 发送TCP数据(send在待发送数据量大于己端缓存区剩余空间时,数据丢失,不会发完)
s.sendall() 发送完整的TCP数据(本质就是循环调用send,sendall在待发送数据量大于己端缓存区剩余空间时,数据不丢失,循环调用send直到发完)
s.recvfrom() 接收UDP数据
s.sendto() 发送UDP数据
s.getpeername() 连接到当前套接字的远端的地址
s.getsockname() 当前套接字的地址
s.getsockopt() 返回指定套接字的参数
s.setsockopt() 设置指定套接字的参数
s.close() 关闭套接字 面向锁的套接字方法
s.setblocking() 设置套接字的阻塞与非阻塞模式
s.settimeout() 设置阻塞套接字操作的超时时间
s.gettimeout() 得到阻塞套接字操作的超时时间
socketserver模块
详细解析
socket实现并发的模块
基于tcp的套接字,关键就是两个循环,一个链接循环,一个通信循环
socketserver模块中分两大类:server类(解决链接问题)和request类(解决通信问题)
借由继承socketserver.BaseRequestHandler,并覆写其handle方法实现并发服务器。即,每过来一个客户端,就会实例化一个自己继承的子类的对象与其通信
class Myserver(socketserver.BaseRequestHandler):
def handle(self):
print(self.request) #conn
print(self.client_address)#addr while True:
data = self.request.recv(1024)
self.request.sendall(data.upper()) s = socketserver.ThreadingTCPServer(('127.0.0.1',8080),MyServer) #注意这里第二参数为自定义子类
s.serve_forever() #链接循环
urllib模块
可以通过url返回下载页面的结果的函数
from urllib.request import urlopen
return urlopen(url).readlines()
functools模块
functools.partial(iter,li) #偏函数,即绑定参数,第一个参数为要操作的函数,第二参数为操作函数的第一个参数。
select模块
# select 模拟一个socket server,注意socket必须在非阻塞情况下才能实现IO多路复用。
# 接下来通过例子了解select 是如何通过单进程实现同时处理多个非阻塞的socket连接的。
#server端 import select
import socket
import queue server = socket.socket()
server.bind(('localhost',9000))
server.listen(1000) server.setblocking(False) # 设置成非阻塞模式,accept和recv都非阻塞
# 这里如果直接 server.accept() ,如果没有连接会报错,所以有数据才调他们
# BlockIOError:[WinError 10035] 无法立即完成一个非阻塞性套接字操作。
msg_dic = {}
inputs = [server,] # 交给内核、select检测的列表。
# 必须有一个值,让select检测,否则报错提供无效参数。
# 没有其他连接之前,自己就是个socket,自己就是个连接,检测自己。活动了说明有链接
outputs = [] # 你往里面放什么,下一次就出来了 while True:
readable, writeable, exceptional = select.select(inputs, outputs, inputs) # 定义检测
#新来连接 检测列表 异常(断开)
# 异常的也是inputs是: 检测那些连接的存在异常
print(readable,writeable,exceptional)
for r in readable:
if r is server: # 有数据,代表来了一个新连接
conn, addr = server.accept()
print("来了个新连接",addr)
inputs.append(conn) # 把连接加到检测列表里,如果这个连接活动了,就说明数据来了
# inputs = [server.conn] # 【conn】只返回活动的连接,但怎么确定是谁活动了
# 如果server活动,则来了新连接,conn活动则来数据
msg_dic[conn] = queue.Queue() # 初始化一个队列,后面存要返回给这个客户端的数据
else:
try :
data = r.recv(1024) # 注意这里是r,而不是conn,多个连接的情况
print("收到数据",data)
# r.send(data) # 不能直接发,如果客户端不收,数据就没了
msg_dic[r].put(data) # 往里面放数据
outputs.append(r) # 放入返回的连接队列里
except ConnectionResetError as e:
print("客户端断开了",r)
if r in outputs:
outputs.remove(r) #清理已断开的连接
inputs.remove(r) #清理已断开的连接
del msg_dic[r] ##清理已断开的连接 for w in writeable: # 要返回给客户端的连接列表
data_to_client = msg_dic[w].get() # 在字典里取数据
w.send(data_to_client) # 返回给客户端
outputs.remove(w) # 删除这个数据,确保下次循环的时候不返回这个已经处理完的连接了。 for e in exceptional: # 如果连接断开,删除连接相关数据
if e in outputs:
outputs.remove(e)
inputs.remove(e)
del msg_dic[e] #*************************client
import socket
client = socket.socket() client.connect(('localhost', 9000)) while True:
cmd = input('>>> ').strip()
if len(cmd) == 0 : continue
client.send(cmd.encode('utf-8'))
data = client.recv(1024)
print(data.decode()) client.close()
selectors模块
封装好的IO复用模块(select,poll,epoll)
sel = selectors.DefaultSeletors() # 首先创建根据操作系统取一个最好的IO复用方式(前提是存在)
sel.reister(sock,selectors.EVENT_READ,myaccept) #也就要对sock和myaccept函数做一个绑定,只要sock有活动,直接调用myaccpet方法
sel.unregister(conn)解除conn绑定的函数
events = sel.select() # 获得激活状态的事件
from socket import *
import selectors sel=selectors.DefaultSelector()
def accept(server_fileobj,mask):
conn,addr=server_fileobj.accept()
sel.register(conn,selectors.EVENT_READ,read) def read(conn,mask):
try:
data=conn.recv(1024)
if not data:
print('closing',conn)
sel.unregister(conn)
conn.close()
return
conn.send(data.upper()+b'_SB')
except Exception:
print('closing', conn)
sel.unregister(conn)
conn.close() server_fileobj=socket(AF_INET,SOCK_STREAM)
server_fileobj.setsockopt(SOL_SOCKET,SO_REUSEADDR,1)
server_fileobj.bind(('127.0.0.1',8088))
server_fileobj.listen(5)
server_fileobj.setblocking(False) #设置socket的接口为非阻塞
sel.register(server_fileobj,selectors.EVENT_READ,accept) #相当于网select的读列表里append了一个文件句柄server_fileobj,并且绑定了一个回调函数accept while True:
events = sel.select() # 获得激活状态的事件
for key, mask in events:
callback = key.data # 传入函数
callback(key.fileobj, mask) #mask暂时没有意义
platform模块
>>> platform.system() #返回系统名称
'Windows' #linux
>>> platform.system()
'Linux'
paramiko模块
SSH远程连接有两种方式,一种是通过用户名和密码直接登录,另一种则是用过密钥登录
requests模块
# 第三方模块,pip install requests
# 可以模仿浏览器请求web服务器 # get方式请求
requests.get(url='https://www.bilibili.com/video/av21534444/')
# 1.1 get方式带参数
requset.get(url='https://www.bilibili.com/video/av21534444/?p=4&a=1')
# 1.2 get方式带参数(借由params参数,)
#注意的是params参数无论是get请求,还是post请求,都是放在url的‘?’后面
requset.get(url='https://www.bilibili.com/video/av21534444/',params={'p':4,'a':1}) #获得数据
data =requset.get(url='https://www.bilibili.com/video/av21534444/',params={'p':4,'a':1})
data.text # 整个html文本
data.json() # 将获得的数据进行json.load()后返回
# post方式 # 注意的是,会有csrf验证阻止,需要使用以下装饰器装饰指定视图 from django.views.decorators.csrf import csrf_exempt # 还有使用data参数是存放post数据,params是get数据 requset.post(url='https://www.bilibili.com/video/av21534444/',data={'p':4,'a':1}) # 还要注意的是data参数是一个字典,但是该字典的value值不能也是个字典(ajax请求也一样),如果是,则会被转化为列表(只剩下键)。
# 要通过序列化的参数json,并且django的视图,要从request.body中取。(额外知识:request.body只能用于post请求,因为get请求requset.body会没有值而报错)
requset.post(url='https://www.bilibili.com/video/av21534444/',json={'p':4,'a':{1:1,2:2}}) # 返回值 response = request.get(url='xxx')
response.content #字节
response.text #字符串 response.encoding = response.apparent_encoding #指定编码为其网页指定的 # cookies
response.cookies.get_dict()
requset.get(url='xx',cookie={'xx':'xx'})
重要参数说明
BeautifulSoup模块
# 帮助html,结构化为对象
pip3 install beautifulsoup4
from bs4 import BeautifulSoup html_doc = """
<html><head><title>The Dormouse's story</title></head>
<body>
asdf
<div class="title">
<b>The Dormouse's story总共</b>
<h1>f</h1>
</div>
<div class="story">Once upon a time there were three little sisters; and their names were
<a class="sister0" id="link1">Els<span>f</span>ie</a>,
<a href="http://example.com/lacie" class="sister" id="link2">Lacie</a> and
<a href="http://example.com/tillie" class="sister" id="link3">Tillie</a>;
and they lived at the bottom of a well.</div>
ad<br/>sf
<p class="story">...</p>
</body>
</html>
""" soup = BeautifulSoup(html_doc, features="lxml")
# 找到第一个a标签
tag1 = soup.find(name='a')
# 找到所有的a标签
tag2 = soup.find_all(name='a')
# 找到id=link2的标签
tag3 = soup.select('#link2') 常用方法属性整理
使用BeautifulSoup提取文章简介
from bs4 import BeautifulSoup
bs = BeautifulSoup(s,'html.parser')
bs.text
过滤XSS
# XSS的危害:相当于让浏览器执行一堆可执行的脚本 from bs4 import BeautifulSoup
bs = BeautifulSoup(s,'html.parser')
for tag in bs.find_all(): #内部递归遍历文档树
if tag.name in ['script','link']:
tag.decompose() #从文档树中删除
article_detail=str(bs) #获得过滤后的html字符串
concurrent模块
线程池和进程池
from concurrent.futures import ThreadPoolExecutor
pool = ThreadPoolExecutor(10)
for item in task['data']:
hostname = item['hostname']
pool.submit(self.run, hostname)
pool.shutdown(wait=True)
def run(self, hostname):
server_info = plugins.get_server_info(hostname)
server_json = Json.dumps(server_info.data)
self.post_asset(server_json, self.callback)
Gevent模块
SMTP模块(邮件模块)
redis 模块
redis-py提供管道,管道可以看作redis的批处理技术。
redis-py默认是设置一个值就要链接一次。但每次设置一个值都要连接一次,效率非常的低。
所以Redis提供管道技术可以在服务端未响应时,客户端可以继续向服务端发送请求,并最终一次性读取所有服务端的响应。
import redis #事务+一次发送多个命令:
conn = redis.Redis(host='47.94.172.250',port=6379,password='Luffy!4321')
pipe = conn.pipeline(transaction=True)
pipe.multi()
pipe.set('k2','')
pipe.hset('k3','n1',666)
pipe.lpush('k4','laonanhai')
pipe.execute()
#通过yield创建一个生成器完成一点一点获取(通过字典操作的源码来的灵感)
# hscan_iter(切记:一般到公司以后,如果不知道数据到底有多少条,千万不要用hgetall,而用这个)
例如,取出一个key的所有val进行打印(1000w条,hash类型)
方案一:一次取完(不可行)
如果1000w条一次取完,内存爆炸
方案二:一次取一个val(可行,浪费)
每次取1个值都要来回收发,非常低效
方案三:折中做法(迭代器做法,就是这个)
一次发个100条,读完再发 def list_iter(key, count=100):
index = 0
while True:
data_list = conn.lrange('k1', index, index + count - 1)
if not data_list:
return
index += count for item in data_list:
yield item
连接池
本质是维护一个已经和服务端连接成功的socket。以后再次发送数据时,直接从连接池中取一个socket,直接send数据即可。
#!/usr/bin/env python
# -*- coding:utf-8 -*- import redis pool = redis.ConnectionPool(host='10.211.55.4', port=6379) r = redis.Redis(connection_pool=pool)
r.set('foo', 'Bar')
print r.get('foo')
redis的name可以带有通配符,delete不行但可以传入*列表来解包
注意:运维的禁忌,不能用keys(数据一多很麻烦),尽量用scan_iter
python:常用模块 知识整理的更多相关文章
- Python常用模块之sys
Python常用模块之sys sys模块提供了一系列有关Python运行环境的变量和函数. 常见用法 sys.argv 可以用sys.argv获取当前正在执行的命令行参数的参数列表(list). 变量 ...
- Python常用模块中常用内置函数的具体介绍
Python作为计算机语言中常用的语言,它具有十分强大的功能,但是你知道Python常用模块I的内置模块中常用内置函数都包括哪些具体的函数吗?以下的文章就是对Python常用模块I的内置模块的常用内置 ...
- python——常用模块2
python--常用模块2 1 logging模块 1.1 函数式简单配置 import logging logging.debug("debug message") loggin ...
- python——常用模块
python--常用模块 1 什么是模块: 模块就是py文件 2 import time #导入时间模块 在Python中,通常有这三种方式来表示时间:时间戳.元组(struct_time).格式化的 ...
- Python常用模块——目录
Python常用模块学习 Python模块和包 Python常用模块time & datetime &random 模块 Python常用模块os & sys & sh ...
- python 常用模块之random,os,sys 模块
python 常用模块random,os,sys 模块 python全栈开发OS模块,Random模块,sys模块 OS模块 os模块是与操作系统交互的一个接口,常见的函数以及用法见一下代码: #OS ...
- python常用模块之时间模块
python常用模块之时间模块 python全栈开发时间模块 上次的博客link:http://futuretechx.com/python-collections/ 接着上次的继续学习: 时间模块 ...
- python常用模块之subprocess
python常用模块之subprocess python2有个模块commands,执行命令的模块,在python3中已经废弃,使用subprocess模块来替代commands. 介绍一下:comm ...
- python常用模块之string
python常用模块string模块,该模块可以帮我们获取字母.数字.特殊符号. import string #打印所有的小写字母 print(string.ascii_lowercase) #打印所 ...
随机推荐
- rpm -qa|grep jdk
转:http://blog.csdn.net/u012110719/article/details/42002221 RPM是RedHat Package Manager(RedHat软件包管理工具) ...
- hive数据类型1
- 用python做线性规划
scipy.optimize.linprog(c, A_ub=None, b_ub=None, A_eq=None, b_eq=None, bounds=None, method='simplex', ...
- Server2008实验——私钥和添加数据恢复代理程序
导出和安装私钥 当一个用户加密一个文件的时候,生成证书,拥有证书的私钥的用户才能够解开这个加密文件:为了防止私钥丢失导致加密文件不可打开,可以导出私钥给同一个用户组的用户帮忙打开: 1.创建[xl]和 ...
- 英特尔®oneAPI简介及动手实验研讨会召集令
Intel Developer Zone 2019年超级计算大会英特尔正式发布了oneAPI软件行业计划及其beta产品,在上篇文章中我们已为您介绍了oneAPI的基本含义,本文将继续为您介绍oneA ...
- vs2017安装过程中下载不动的一种情况
第一种可能:微软可能有不同的下载地址,某些地址下载速度快,某些慢.这种情况下,禁用连接,再启用.有几率速度飞速上升. 第二种可能:由于总所周知的原因,连接不了Google.但是如果需要下载Androi ...
- AttributeError: module 'unittest' has no attribute 'TestCase'
一个自己给自己挖的坑 大家千万不要用库的名称命名,特别是刚刚入门的时候.文件夹.文件,都不要用库的名称. 一旦与库重名,就会出现这种 AttributeError. 引以为戒,以后我再这么命名,我就是 ...
- Power Management of Hybrid DRAM/PRAM-Based Main Memory
0.ABSTRACT (1)non-volatile memory——low standby power DRAM——high performance and better active power ...
- JavaScript--QuckStudy
Day1: 初识JS: https://www.liaoxuefeng.com/wiki/1022910821149312 >打印: alert('我要学JavaScript!'); >J ...
- 从入门到自闭之Python--MySQL数据库的单表操作
单表查询:select * from 表 where 条件 group by 分组 having 过滤 order by 排序 limit n; 语法: select distinct 字段1,字段2 ...