阅读目录:
一、time模块
二、datetime模块
三、random模块
四、os模块
五、sys模块
六、shutil模块
七、shelve模块
八、suprocess 模块
九、paramiko模块
十、configparser模块
十二、logging模块
十三、序列化模块 json&pickle模块
十四、hash模块
十五、正则模块re
一、time模块,时间的三种格式(重点)
1、time.time --unix元年(1970年1月1日00:00:00)时间到当前时间,一共有多少秒
import time
print(time.time())
>>:1527000352.3488626
#unix元年(1970年1月1日00:00:00)时间到当前时间,一共有多少秒
2、time.strftime --格式化时间,可以自定义时间格式
import time
print(time.strftime("%Y-%m-%d %X"))
>>:格式化的时间字符串:'2018-05-22 22:47:41'
# %Y:年,%m:月,%d:日,%X:当前时间(时:分:秒)的格式,%X==%H:%M:%S
3、struct_time --结构化时间,取得是当前时区的时间
import time
print(time.localtime()) #时间对象(把一个完整的时间拆分成一个个小的部分,方便单独取值)
>>:time.struct_time(tm_year=2018, tm_mon=5, tm_mday=22, tm_hour=22, tm_min=52, tm_sec=26, tm_wday=1, tm_yday=142, tm_isdst=0)
print(time.localtime().tm_year) #取时间对象内的参数(tm_year)得到对应的值(年)
>>:2018
print(time.localtime().tm_mon) #取时间对象内的参数(tm_mon)得到对应的值(月)
>>:5
print(time.localtime().tm_mday) #取时间对象内的参数(tm_mday)得到对应的值(日)
>>:22
print(time.localtime().tm_hour) #取时间对象内的参数(tm_hour)得到对应的值(时象)
>>:23
4、time.gmtime与struct_time结构一样,只不过time.gmtime取得时间是 [GMT时区(世界标准时间)的时间对象]
import time
print(time.gmtime())
# time.struct_time(tm_year=2018, tm_mon=10, tm_mday=6, tm_hour=15, tm_min=53, tm_sec=56, tm_wday=5, tm_yday=279, tm_isdst=0)
print(time.gmtime().tm_year)
# 2018
print(time.gmtime().tm_mon)
# 10
print(time.gmtime().tm_mday)
# 6
print(time.gmtime().tm_hour)
# 15
print(time.gmtime().tm_sec)
# 56
1.2、时间之间的转换关系(了解)
图解:
1)、时间戳 (123123) 转换成结构化时间time.localtime() :传入一个数字,单位为秒,得到的值就是Unix元年加上这个秒数后的日期
import time
print(time.localtime(123123)) #123123秒
>>:time.struct_time(tm_year=1970, tm_mon=1, tm_mday=2, tm_hour=18, tm_min=12, tm_sec=3, tm_wday=4, tm_yday=2, tm_isdst=0)
print(time.gmtime(123123)) #123123秒
>>:time.struct_time(tm_year=1970, tm_mon=1, tm_mday=2, tm_hour=10, tm_min=12, tm_sec=3, tm_wday=4, tm_yday=2, tm_isdst=0)
2)、把结构化时间 time.localtime() 转换成时间戳(单位/秒)
import time
print(time.mktime(time.localtime()))
>>:1527002000.0
3)、结构化的时间 time.localtime() 转换成 年-月-日 的形式
import time
print(time.strftime('%Y-%m-%d',time.localtime()))
# 2018-10-07
4)、把格式化的 年-月-日 时间转换成结构化时间
import time
print(time.strptime('2017-05-22','%Y-%m-%d'))
>>:time.struct_time(tm_year=2017, tm_mon=5, tm_mday=22, tm_hour=0, tm_min=0, tm_sec=0, tm_wday=0, tm_yday=142, tm_isdst=-1)
5)、其他时间格式
import time
time.sleep(3) #等待3秒在执行
print(time.asctime(time.localtime())) #linux服务器时间格式(转换本地时间)
>>:Tue May 22 23:27:21 2018
print(time.ctime(123123)) #时间戳形式
>>:Fri Jan 2 18:12:03 1970
6)、asctime与ctime的区别与使用
图解:
区别:ctime可以把时间戳转换成%a %b %d %H %M %S %Y这种格式
asctime可以把结构化时间换成%a %b %d %H %M %S %Y这种格式
例子:
import time
print(time.asctime(time.localtime()))
# Sun Oct 7 00:51:56 2018
print(time.ctime(123123))
# Fri Jan 2 18:12:03 1970
二、时间模块 datatime
2.1、datatime使用
import datetime
print(datetime.datetime.now()) #打印当前时间
# >>:2018-05-22 23:33:57.233285
print(datetime.datetime.now().replace(year=1999,hour=3)) #把当前时间的"年"替换成了1999年,"小时"替换成了3
# >>:1999-05-23 03:08:38.648744
print(datetime.datetime.fromtimestamp(123123)) #打印时间戳对应的时间(年-月-日)
# >>:1970-01-02 18:12:03
print(datetime.datetime.now() + datetime.timedelta(days=3)) #打印三天后的当前时间
print(datetime.datetime.now() + datetime.timedelta(days=-3)) #打印三天前的当前时间
print(datetime.datetime.now() + datetime.timedelta(weeks=3)) #打印三周后的当前时间
print(datetime.datetime.now() + datetime.timedelta(weeks=-3)) #打印三周前的当前时间
三、随机模块random
3.1、随机模块random重点掌握
import random
print(random.randint(1,3)) #随机取1~3之间的任意一个整数
# 1或2或3
print(random.choice([1,'a','b',3])) #在指定的[1,'a','b',3]中随机取1个值
# 1,'a','b',3这几个里面随机取一个值
3.2、随机模块random了解知识点
import random
print(random.random()) #默认取得值是0~1之间的小数
# 0.14528372626216834
print(random.randint(1,3)) #随机取1~3之间的任意一个整数
# 1或2或3
print(random.randrange(1,3)) #由于使用了range(顾头不顾尾),所以随机只能取到1或者2
# 1或2
print(random.choice([1,'a','b',3])) #在指定的[1,'a','b',3]中随机取1个值
# 1,'a','b',3这几个里面随机取一个值
print(random.sample([1,'a','b',3],2)) #在指定的[1,'a','b',3]中随机取2个值,然后组合成一个列表
# ['a', 'b']
print(random.uniform(1,3)) #取1~3之间随机的一个小数
# 2.6304200041904804
list=[1,3,5,7,9]
random.shuffle(list) #洗牌,也就是重新将这个列表里面的值打乱顺序
print(list)
# [7, 3, 5, 9, 1]
3.3、补充:chr 将十进制的数字按照ASCII表转成字母,而ord 正好相反,把字母转换成数字
print(chr(65))
# A
print(chr(90))
# Z
print(ord('A'))
# 65
print(ord('Z'))
# 90
3.4、生成随机验证码功能 [数字+大小写字母+特殊字符]
import random
def make_code(num=5):
res=''
for n in range(num):
s1=str(random.randint(0,9)) # 取一个字符串类型的随机数字(因为后面需要用'+'号拼接,所以要用str(random.randint(0,9)))
s2=chr(random.randint(65,90)) # 取一个随机的大写字母
s3=s2.lower() # 取一个随机的小写字母
s4=random.choice(['!','@','#','$','%','^','&','*']) # 取一个特殊字符
res+=random.choice([s1,s2,s3,s4]) # 将s1,s2,s3,s4字符拼接起来
print(res)
make_code(20)
>>: czzBd&C0z0@y#Y^AaZ@! #最终拿到了一个20位数随机码
四、os模块 -- os模块是与操作系统交互的一个接口
import os
print(os.getcwd()) #获取当前工作目录,即当前python脚本工作的目录路径,相当于Linux下的"pwd"
print(os.chdir()) #改变当前脚本工作目录;相当于shell下cd
print(os.curdir) #返回当前目录: ('.')
os.pardir #获取当前目录的上一个目录:('..')
os.makedirs('dirname1/dirname2') #递归创建目录,相当于linux下的 "mkdir -p"
os.removedirs('dirname1') #递归的删除目录
os.mkdir('dirname') #在当前目录下创建目录
os.rmdir('dirname') #删除单级空目录,若目录不为空则无法删除,报错;相当于shell中rmdir dirname
os.listdir('.') #列出指定目录下的所有文件和子目录,包括隐藏文件,并以列表方式打印
os.remove() #删除一个文件
os.rename("oldname","newname") #重命名文件/目录
os.stat('path/filename') #获取文件/目录信息
os.sep #输出操作系统特定的路径分隔符,win下为"\\",Linux下为"/"
os.linesep #输出当前平台使用的行终止符,win下为"\t\n",Linux下为"\n"
os.pathsep #输出用于分割文件路径的字符串 win下为;,Linux下为:
os.name #输出字符串指示当前使用平台。win->'nt'; Linux->'posix'
os.system("bash command") #运行shell命令,直接显示
os.environ #获取系统环境变量
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的大小
4.1、os模块几个要记住的用法
1.打印当前目录下所有的文件,类似 ls
import os
print(os.listdir(r'.')) #打印当前目录下的所有文件
>>:['test.txt', 'test.xml', 'test.xml.swap', '第七节课.py']
2.使用os.system可以执行系统命令 --不能拿到执行命令后的结果
import os
os.system('ipconfig') #使用os.system执行系统命令,把执行命令后的结果输出到屏幕
res=os.system('ipconfig') #把命令执行的结果赋值给res,类似linux下的"echo "$?" "
print(res)
# >>:0 #返回"0"表示命令执行成功
# >>:1 #返回"1"表示命令执行失败
使用os.system执行系统命令,把执行命令后的结果输出到屏幕,虽然可以通过赋值操作给一个变量值,但是只能拿到'0'和'1',而不能拿到执行命令后的结果,这里可以通过(suprocess模块)实现。
3、打印当前文件的绝对路径
方式一:
import os
res=os.path.join(
os.path.abspath(__file__), #获取当前文件名
'..', #获取上一级目录".."
'..' #获取上一级目录".."
)
print(os.path.normpath(res)) #使用os.path.normpath,得到当前文件的绝路径(根路径)
>>:C:\Users\stsud\Desktop\Pycharm文档
方式二:
import os
os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
五、sys模块
1、sys.argv #命令行参数List,第一个元素是程序本身路径
2、sys.exit(n) #退出程序,正常退出时exit(0)
3、sys.version #获取Python解释程序的版本信息
4、sys.path #返回模块的搜索路径,初始化时使用PYTHONPATH环境变量的值
5、sys.platform #返回操作系统平台名称
例子:
import sys
print(sys.argv)
>>:['C:/Users/stsud/Desktop/Pycharm文档/第七次课/第七节课.py']
sys.exit(0) #退出程序,正常退出时exit(0)
print(sys.version) #查看Python解释器的版本信息
>>:3.6.4 (v3.6.4:d48eceb, Dec 19 2017, 06:54:40) [MSC v.1900 64 bit (AMD64)]
print(sys.path) #返回模块的搜索路径,初始化时使用PYTHONPATH环境变量的值
>>:['C:\\Users\\stsud\\Desktop\\Pycharm文档\\第七次课', 'C:\\Users\\stsud\\Desktop\\Pycharm文档', 'C:\\Install Path\\Python3.6\\python36.zip', 'C:\\Install Path\\Python3.6\\DLLs', 'C:\\Install Path\\Python3.6\\lib', 'C:\\Install Path\\Python3.6', 'C:\\Install Path\\Python3.6\\lib\\site-packages', 'C:\\Install Path\\Python3.6\\lib\\site-packages\\pip-10.0.1-py3.6.egg', 'C:\\Install Path\\Pycharm-破解版\\PyCharm 2018.1\\helpers\\pycharm_matplotlib_backend']
print(sys.platform) #返回操作系统平台名称
>>:win32
5.1、利用sys模块打印进度条:基础进阶
#进度条功能:手动面条版
import sys,time
print('\r[#####]',end='') #"\r"表示每次打印的内容都从第一行开始(相当于第二次打印的内容会覆盖掉第一次打印的内容)
time.sleep(1)
print('\r[######]',end='') #"\r"表示每次打印的内容都从第一行开始(相当于第二次打印的内容会覆盖掉第一次打印的内容)
time.sleep(1)
print('\r[#######]',end='') #"\r"表示每次打印的内容都从第一行开始(相当于第二次打印的内容会覆盖掉第一次打印的内容)
time.sleep(1)
print('\r[############]',end='') #end='' 表示把每一行的换行符替换为空
[######]
#进度条功能:手动面条版-升级
import sys,time
print('[%-50s]' %'#') #'[%-50s]'其中"-50"表示左对齐,宽度为50,%s还是用来传值的
print('[%-50s]' %'##')
print('[%-50s]' %(int(0.3*50)*'#')) #(int(0.3*50)*'#'),数字与字符相乘==(15*'#')
print('[%-50s]' %(int(1*50)*'#')) #(int(1*50)*'#'),数字与字符相乘==(50*'#')
print('%d%%' %30) #2个%%表示取消%的特殊意义,就只是一个普通的字符"%",那么%d=30,%%=%,得出30%
print(('[%%-%ss]' %50) %'#######') #('[%%-%ss]' %50)给传一个值50进去后就会得到[%-50s]
#进度条功能:综合升级版
import sys,time
def jindutiao(precent,width=50):
print(('\r[%%-%ss]' %width) %(int(precent * width) * '#'),end='')
# print('\r[%%-%ss]' % width) 拿到的值为:[%-50s]
# %(int(precent * width) * '#') 拿到的值为:'#'
# 二者合一拿到的为:('[%-50s]' %'#') == [# ]
total_size=102400 #下载总量
resv_size=0 #接受量为0
# 通过循环覆盖的过程来实现进度条增长!
while resv_size < total_size: #接受量小于下载总量时
time.sleep(0.1)
resv_size+=1024 #每次下载1024
precent=resv_size / total_size #已下载量除以下载总量得到一个百分比
jindutiao(precent) #把得到的百分比传到函数jindutiao里面
5.2、利用sys模块打印进度条:完整功能
#进度条功能:综合完整版
import sys,time
def jindutiao(precent,width=50): #主体函数
if precent>1: #如果百分比大于100%时,把它固定死,不能超过100%
precent=1
show_str=('\r[%%-%ss]' %width) %(int(precent * width) * '#')
# show_str 拿到的值为:[##################################################] 末尾没有百分比%
print( '\r%s %d%%' % (show_str,int(precent * 100)),end='' )
# %s用来接收show_str的值
# %d用来接收int(precent * 100)的值,接收的字符类型为整数
# %%就是一个%号
#################################上面为主体函数-可套用################################
#测试进度条功能
total_size=102400 #下载总量
resv_size=0 #接受量为0
while resv_size < total_size: #接受量小于下载总量时
time.sleep(0.1)
resv_size+=1024 #每次下载1024
precent=resv_size / total_size #已下载量除以下载总量得到一个百分比
jindutiao(precent) #把得到的百分比传到函数jindutiao里面
六、shutil模块 --高级的文件、文件夹、压缩包处理模块
6.1、将 test.txt 的文件内容拷贝到另一个文件 new.txt 中
import shutil
shutil.copyfileobj(open('test.txt','r'), open('new.txt', 'w'))
原理:将test.txt以"r"只读的模式读出文件内容,然后以"w"写的模式把读出的文件内容写到新的new.txt文件中。
6.2、拷贝文件
import shutil
shutil.copyfile('new.txt', 'new2.txt') #目标文件无需存在
6.3、仅拷贝权限。内容、组、用户均不变
import shutil
shutil.copymode('f1.log', 'f2.log') #目标文件必须存在
6.4、仅拷贝状态的信息,包括:mode bits, atime, mtime, flags
import shutil
shutil.copystat('f1.log', 'f2.log') #目标文件必须存在
6.5、拷贝文件和权限
import shutil
shutil.copy('f1.log', 'f2.log')
6.6、拷贝文件和状态信息
import shutil
shutil.copy2('f1.log', 'f2.log')
6.7、递归的去拷贝文件夹
import shutil
shutil.copytree('folder1', 'folder2', ignore=shutil.ignore_patterns('*.pyc', 'tmp*')) #目标目录不能存在,注意对folder2目录父级目录要有可写权限,ignore的意思是排除
6.8、递归的去移动文件,它类似mv命令,其实就是重命名。
import shutil
shutil.move('folder1', 'folder3')
6.9、shutil.make_archive 打包文件
import shutil
ret = shutil.make_archive("test_bak", 'gztar', root_dir=r'C:\Users\stsud\Desktop\Pycharm文档\第七次课')
注释:
test_bak 打包后命名为"test_bak.tar.gz"
gztar 以tar的方式打包文件
root_dir 被打包的文件
6.10、tarfile 解压文件
import tarfile
f=tarfile.open('test_bak.tar.gz','r')
f.extractall(r'C:\Users\stsud\Desktop\Pycharm文档\第八节课')
f.close()
注释:
tarfile.open('test_bak.tar.gz','r') 以'r'只读模式打开test_bak.tar.gz文件
f.extractall(r'C:\Users\stsud\Desktop\Pycharm文档\第八节课') 文件解压后存放的目录
f.close() 文件打开后需要被关闭
shutil 对压缩包的处理是调用 zipfile 和 tarfile 两个模块来进行的,详细:
6.10.1、zipfile 模块压缩与解压
import tarfile
打包
t=tarfile.open('test.tar.gz','w')
t.add('test.txt')
t.close()
注释:
test.tar.gz 打包后的文件名,以'w'的方式打开
t.add('test.txt') 打包的文件名
t.close() 打包完毕后关闭文件
解压
t=tarfile.open('test.tar','r')
t.extractall(r'C:\Users\stsud\Desktop\Pycharm_Document\第七次课')
t.close()
注释:
data.tar.gz 需要被解压的文件,以只读模式打开
f.extractall 指定解压的目录
f.close() 解压完毕后关闭
七、shevle 模块 ---只支持Python格式的数据类型
7.1、把内容写到文件里面
import shelve
f=shelve.open(r'shelve.txt') #打开一个文件并写入内容,并存在磁盘里面
f['a']={'age':18,'sex':'male'}
f['b']={'age':38,'sex':'famale'}
f.close()
7.2、文件写好后,取值的话,按照正常的方式取值就可以了
import shelve
f=shelve.open(r'shelve.txt') #打开一个文件并写入内容,并存在磁盘里面
f['a']={'age':18,'sex':'male'}
f['b']={'age':38,'sex':'famale'}
print(f['a']) #取出'a'的所有值
>>:{'age': 18, 'sex': 'male'}
print(f['b'])
>>:{'age': 38, 'sex': 'famale'}
print(f['b']['age']) #取出'a'里面的'age'的值
>>:38
print(f['b']['sex'])
>>:famale
f.close()
7.3、修改文件内容
import shelve
f=shelve.open(r'shelve.txt',writeback='True') #要加writeback='True',表示写回
f['a']={'age':18,'sex':'male'}
f['b']={'age':38,'sex':'famale'}
f['a']['age']=19 #修改文件内内容'age'为19
print(f['a']['age'])
>>:19
f.close()
八、suprocess 模块 ---可执行系统命令的模块(或者在cmd命令中运行的程序)
8.1、执行正确的命令之后的返回值给管道,通过stdout=subprocess.PIPE获取
import subprocess
obj=subprocess.Popen(
'ipconfig', # 'ipconfig' 要执行的命令,输入的命令必须是字符串形式。
shell=True, # shell=True 调用'命令解释器'来执行'ipconfig'这个命令。
stdout=subprocess.PIPE, # stdout=subprocess.PIPE 即管道(命令执行后结构给到管道),stdout表示输入正确的命令得到的返回值。
stderr=subprocess.PIPE, # stderr=subprocess.PIPE # stderr表示输入错误的命令得到的返回值。
)
stdout=obj.stdout.read() # 把管道内的值(执行命令后得到的值)赋值给stdout
print(stdout.decode('gbk')) # 不加字符集得到的是二进制形式的返回值,这里要使用操作系统所使用的字符集('gbk')
>>: 映像名称 PID 会话名 会话# 内存使用
>>: ========================= ======== ================ =========== ============
>>: System Idle Process 0 Services 0 8 K
>>: System 4 Services 0 24 K
>>: Registry 120 Services 0 13,280 K
8.2、输入错误的命令之后的返回值给管道,通过stderr=subprocess.PIPE获取
import subprocess
obj=subprocess.Popen(
'taskliasdasdst', # 'taskliasdasdst' 要执行的命令,输入的命令必须是字符串形式。
shell=True, # shell=True 需要调用命令解释器来帮我执行'tasklist'这个命令
stdout=subprocess.PIPE, # stdout=subprocess.PIPE 即管道(命令执行后结构给到管道),stdout表示输入正确的命令得到的返回值
stderr=subprocess.PIPE, # stderr=subprocess.PIPE # stderr表示输入错误的命令得到的返回值
)
stderr=obj.stderr.read() # 把管道内的值(执行命令后得到的值)赋值给stdout
print(stderr.decode('gbk')) # 不加字符集得到的是二进制形式的返回值,这里要使用操作系统所使用的字符集('gbk')
>>: 'taskliasdasdst' 不是内部或外部命令,也不是可运行的程序
>>: 或批处理文件。
8.3、suprocess(翻译过来:子进程)不单单只是一个执行命令的模块,在程序运行中,会先运行主进程,主进程可以生产一个子进程,在主进程运行的同时子进程也在运行(相当于并发执行,可提高效率,节省时间)
以下为suprocess模块的正常使用方法。
import subprocess
obj=subprocess.Popen( #执行命令的过程
'tasklist',
shell=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
)
stdout=obj.stdout.read() #拿到执行命令得到的结果
print(stdout.decode('gbk'))
九、paramiko模块 简单执行远程命令的用法
9.1、基于IP和端口连接的用法
#paramiko模块的简单远程执行命令:用法一
import paramiko
# 创建SSH对象--(实例化)
ssh = paramiko.SSHClient()
# 允许连接不在know_hosts文件中的主机 (连接SSH时,输入Yes/No)--固定用法
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
# 连接服务器--指定IP,端口,用户名和密码
ssh.connect(hostname='192.168.200.142', port=22, username='root', password='123456')
# 执行命令 --执行"df -h"命令
stdin, stdout, stderr = ssh.exec_command('df -h') #把执行命令得到的结果放在管道里面
#stdin 标准输入
#stdout 标准输出
#stderr 标准错误
# 获取命令结果--获取正确的结果
result = stdout.read()
print(result.decode('utf-8')) # windows系统为gbk编码,linux系统为utf-8编码
# 关闭连接
ssh.close()
# 得到的值:
Filesystem Size Used Avail Use% Mounted on
/dev/sda3 8.6G 1.5G 6.7G 19% /
tmpfs 497M 0 497M 0% /dev/shm
/dev/sda1 190M 35M 146M 19% /boot
paramiko模块的简单远程执行命令:用法二
import paramiko
transport = paramiko.Transport(('192.168.200.142', 22))
transport.connect(username='root', password='123456')
ssh = paramiko.SSHClient()
ssh._transport = transport
stdin, stdout, stderr = ssh.exec_command('df -h')
res=stdout.read()
print(res.decode('utf-8'))
transport.close()
# 得到的值:
Filesystem Size Used Avail Use% Mounted on
/dev/sda3 8.6G 1.5G 6.7G 19% /
tmpfs 497M 0 497M 0% /dev/shm
/dev/sda1 190M 35M 146M 19% /boot
9.2、基于ssh-key秘钥连接的用法(未测试)
import paramiko
private_key = paramiko.RSAKey.from_private_key_file('/tmp/id_rsa')
# 创建SSH对象
ssh = paramiko.SSHClient()
# 允许连接不在know_hosts文件中的主机
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
# 连接服务器
ssh.connect(hostname='120.92.84.249', port=22, username='root', pkey=private_key)
# 执行命令
stdin, stdout, stderr = ssh.exec_command('df')
# 获取命令结果
result = stdout.read()
print(result.decode('utf-8'))
# 关闭连接
ssh.close()
9.3、SFTPClient--用于连接远程服务器并执行上传下载
1.基于用户名密码上传下载
import paramiko
transport = paramiko.Transport(('192.168.200.142', 22))
transport.connect(username='root', password='123456')
sftp = paramiko.SFTPClient.from_transport(transport)
# 将本地的"C:\MLBB\部署记录\2,3,5大区分区部署.txt"文件,上传至服务器并重命名"/root/szq_test.txt" --这里不单单指定上传的目录,必须指定上传后的文件名
sftp.put(r'C:\MLBB\部署记录\2,3,5大区分区部署.txt', '/root/szq_test.txt')
# 将服务器的/etc/passwd文件,下载到本地并重命名"D:\passwd" --同样,下载也是不单单指定下载的目录,必须指定下载后的文件名
sftp.get('/etc/passwd', r'D:\passwd')
transport.close()
2.基于公钥密钥上传下载(未测试)
import paramiko
private_key = paramiko.RSAKey.from_private_key_file('/tmp/id_rsa')
transport = paramiko.Transport(('120.92.84.249', 22))
transport.connect(username='root', pkey=private_key )
sftp = paramiko.SFTPClient.from_transport(transport)
# 将location.py 上传至服务器 /tmp/test.py
sftp.put('/tmp/id_rsa', '/tmp/a.txt')
# 将remove_path 下载到本地 local_path
sftp.get('remove_path', 'local_path')
transport.close()
十、configparser模块 --解析配置文件用的模块
配置文件 my.ini 内容:
[egon]
pwd=123
age=18
salary=3.1
is_beautiful=True
[alex]
pwd=3714
age=38
salary=3.2
使用例子:
import configparser
config=configparser.ConfigParser()
config.read('my.ini')
print(config.sections())
# ['egon', 'alex'] # 取配置文件的文件内容的标题部分
print(config.options('egon'))
# ['pwd', 'age', 'salary', 'is_beautiful'] # 取配置文件的文件内容标题对应的内容部分
print(config.getint('egon','age')) # 使用getint相当于是给取到的值的类型做了int处理,即int(value)
# 18 # 取配置文件的文件内容标题对应的内容部分(key)对应的值(整数)
print(config.getfloat('egon','salary'))
# 3.1 # 取配置文件的文件内容标题对应的内容部分(key)对应的值(小数)
print(config.getboolean('egon','is_beautiful'))
# True # 取配置文件的文件内容标题对应的内容部分(key)对应的值(布尔类型)
十二、logging模块
1、日志的级别,默认日志级别为"warning"级别,默认打印到终端。
五: critical 对应数字: 50
四: error 对应数字: 40
三: warning 对应数字: 30
二: info 对应数字:20
一: debug 对应数字:10
import logging
logging.debug('debug级别')
logging.info('info级别')
logging.warning('warning级别')
logging.error('error级别')
logging.critical('critical级别')
WARNING:root:warning级别
ERROR:root:error级别
CRITICAL:root:critical级别
注释:
WARNING:日志级别
:(分隔符)
root:日志名
warning级别:日志的信息
2、为logging模块指定全局配置,针对所有logger有效,控制日志信息打印到文件中
可在logging.basicConfig()函数中通过具体参数来更改logging模块默认行为,
1、可用参数有:
filename :用指定的文件名创建FiledHandler(后边会具体讲解handler的概念),这样日志会被存储在指定的文件中。
filemode :文件打开方式,在指定了filename时使用这个参数,默认值为“a”还可指定为“w”。
format :指定handler使用的日志显示格式。
datefmt :指定日期时间格式。
level :设置rootlogger的日志级别
stream :用指定的stream创建StreamHandler。可以指定输出到sys.stderr,sys.stdout或者文件,默认为
sys.stderr :若同时列出了filename和stream两个参数,则stream参数会被忽略。
1.1、format(格式)参数:
%(name)s :Logger的名字,并非用户名,详细查看
%(levelno)s :数字形式的日志级别
%(levelname)s :文本形式的日志级别
%(pathname)s :调用日志输出函数的模块的完整路径名,可能没有
%(filename)s :调用日志输出函数的模块的文件名
%(module)s :调用日志输出函数的模块名
%(funcName)s :调用日志输出函数的函数名
%(lineno)d :调用日志输出函数的语句所在的代码行
%(created)f :当前时间,用UNIX标准的表示时间的浮 点数表示
%(relativeCreated)d:输出日志信息时的,自Logger创建以 来的毫秒数
%(asctime)s :字符串形式的当前时间。默认格式是 “2003-07-08 16:49:45,896”。逗号后面的是毫秒
%(thread)d :线程ID。可能没有
%(threadName)s :线程名。可能没有
%(process)d :进程ID。可能没有
%(message)s :用户输出的消息
3、如何使用 --简单了解用法,右键运行后,日志信息将会被输入到当前目录下的access.log文件里面
import logging
logging.basicConfig(
filename='access.log', #指定日志输出到指定文件,默认路径为当前路径
format='%(asctime)s - %(name)s - %(levelname)s -%(module)s: %(message)s', #format格式的参数,-号为分隔符(可自定义)
datefmt='%Y-%m-%d %H:%M:%S %p', #专门用来定制日志的时间格式
level=10 #日志级别
)
logging.debug('debug级别')
logging.info('info级别')
logging.warning('warning级别')
logging.error('error级别')
logging.critical('critical级别')
4、logging模块可以分成四类对象
logging对象 作用:产生日志
handler对象 作用:控制日志的去向(日志信息输出到哪里),1日志信息输出到文件,2日志信息输出到终端。
formatter对象 作用:定制日志的格式
filter对象 作用:过滤日志(不常用)
图解:
4.1、基于logging模块的四类对象,对logging模块的简单用法:
import logging
#一、 logging对象 作用:产生日志
logger1=logging.getLogger('银行相关业务') #日志名,区分业务类型
#二、 handler对象 作用:控制日志的去向(日志信息输出到哪里),1日志信息输出到文件,2日志信息输出到终端。
fh1=logging.FileHandler('a1.log',encoding='utf-8')
fh2=logging.FileHandler('a2.log',encoding='utf-8')
ch=logging.StreamHandler() #StreamHandler表示终端
#一+二、 建立logger对象与handler对象的绑定关系
logger1.addHandler(fh1)
logger1.addHandler(fh2)
logger1.addHandler(ch)
#三、 formatter对象 作用:定制日志的格式
formatter1=logging.Formatter(
fmt='%(asctime)s - %(name)s - %(levelname)s -%(module)s: %(message)s',
datefmt='%Y-%m-%d %H:%M:%S %p'
)
formatter2=logging.Formatter(
fmt='%(asctime)s ==> %(message)s',
)
#二+三、 为handler对象绑定日志格式
fh1.setFormatter(formatter1)
fh2.setFormatter(formatter2)
ch.setFormatter(formatter2)
#四、 设置日志级别,两层关卡(第一层:logger对象,第二层:handler对象),只有两层都放行,最终日志才会产生
logger1.setLevel(10)
fh1.setLevel(10)
fh2.setLevel(10)
ch.setLevel(10)
#五、 调用Logging对象产生日志
logger1.debug('这是一条debug日志')
4.2、生产中日志模块及格式的正确用法(setting.py与use.py在同一目录)
1、logging配置,配置文件名setting.py
import os
BASE_DIR=os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
# 定义日志文件的保存路径
logfile_path=os.path.join(BASE_DIR,'log','access.log') #log:存在日志的目录,access.log:文件名
boss_logfile_path=os.path.join(BASE_DIR,'log','boss.log')
# 定义日志格式
standard_format = '[%(asctime)s][%(threadName)s:%(thread)d][task_id:%(name)s][%(filename)s:%(lineno)d]' \
'[%(levelname)s][%(message)s]' #其中name为getlogger指定的名字
simple_format = '[%(levelname)s][%(asctime)s][%(filename)s:%(lineno)d]%(message)s'
id_simple_format = '[%(asctime)s] %(message)s'
# log配置字典
LOGGING_DIC = {
'version': 1,
'disable_existing_loggers': False,
'formatters': {
'standard': {
'format': standard_format
},
'simple': {
'format': simple_format
},
'id_simple': {
'format': id_simple_format
}
},
'filters': {},
'handlers': {
#打印到终端的日志 -- 实际中是不需要打印到终端的
'console': {
'level': 'DEBUG',
'class': 'logging.StreamHandler', # 打印到终端
'formatter': 'simple'
},
#打印到文件的日志,
'default': {
'level': 'DEBUG',
'class': 'logging.FileHandler', # 保存到文件
'formatter': 'standard',
'filename': logfile_path, # 日志文件
'encoding': 'utf-8', # 日志文件的编码,再也不用担心中文log乱码了
},
#打印给boss的日志 -- 单独给某个用户或者自定义日志的级别
'boss': {
'level': 'ERROR',
'class': 'logging.FileHandler', # 保存到文件
'formatter': 'id_simple',
'filename': boss_logfile_path, # 日志文件
'encoding': 'utf-8', # 日志文件的编码,再也不用担心中文log乱码了
},
},
'loggers': {
'': { #这里的key为空
'handlers': ['default', 'console', 'boss'],
'level': 'DEBUG',
'propagate': False,
},
},
}
2、使用,文件名use.py
import logging.config
from setting import LOGGING_DIC
logging.config.dictConfig(LOGGING_DIC) # 导入上面定义的logging配置
logger=logging.getLogger('ATM') #
logger.error('错误')
十三、序列化模块 json&pickle模块
13.1、什么是序列化?
序列化:把内存中的数据转化成一种中间格式(json/pickle格式),然后存放到硬盘,永久保存。
反序列化:从文件中读出(json/pickle格式),然后反解成python的数据类型。
13.2、为什么要序列化?
1.数据结构持久化
2.跨平台数据交互
13.3、如何序列化,反序列化?
1、json
缺点:只能支持部分Python的数据类型
优点:所有的语言都支持json格式
应用:如果需要考虑跨平台性,则需要用json格式
JSON表示的对象就是标准的JavaScript语言的对象,JSON和Python内置的数据类型对应如下:
一、 json序列化例子: dumps与loads
dumps: 把一个字典转换成json格式的字符串 把字典转换为json的字符串
loads: 把json格式的字符串反解成字典 把json的字符串转换为字典
import json
dic={'name':'sudada','age':18}
#序列化
res=json.dumps(dic) #强调,json格式不识别单引号
with open('user.json','w',encoding='utf-8')as f:
f.write(res)
#反序列化
with open('user.json','r',encoding='utf-8')as f:
res=f.read()
dic=json.loads(res)
print(dic)
>>: {'name': 'sudada', 'age': 18}
二、 json序列化例子: dump与load
dump:把一个字典序列化到文件里面
load:直接把文件内容读出来,然后反解成字典
import json
dic={'name':'sudada','age':18}
# 开始序列化 json.dump(dic,f)
with open('user2.json','w',encoding='utf-8')as f:
json.dump(dic,f) #dic为要序列化的对象,f为打开的文件
# 反序列化 json.load(f)
with open('user2.json','r',encoding='utf-8')as f:
dic=json.load(f)
print(dic)
{'name': 'sudada', 'age': 18}
JSON序列化中文时出现乱码(ascii)的问题
import json
dic={'name':'苏大大'}
print(json.dumps(dic)) # 这里打印的不是中文,而是一串ascii码:{"name": "\u82cf\u5927\u5927"}
# 设置ensure_ascii=False即可将ascii码转换为中文
print(json.dumps(dic,ensure_ascii=False)) # {"name": "苏大大"}
2、pickle
缺点:只有Python支持pickle格式
优点:pickle能够支持所有的Python数据类型
应用:如果不需要考虑跨平台性,则需要用pickle格式
一、pickle序列化例子 dumps与loads
dumps: 把一个字典转换成pickle格式的字符串
loads: 把pickle格式的字符串反解成字典
import pickle
dic={'name':'sudada','age':18}
# 序列化
res=pickle.dumps(dic)
with open('user3.pkl','wb')as f:
f.write(res)
#反序列化
with open('user3.pkl','rb')as f:
res=f.read()
dic=pickle.loads(res)
print(dic)
{'name': 'sudada', 'age': 18}
二、pickle序列化例子 dump与load
dump:把一个字典序列化到文件里面
load:直接把文件内容读出来,然后反解成字典
import pickle
dic={'name':'sudada','age':18}
#序列化
with open('user4.pkl','wb')as f:
pickle.dump(dic,f)
#反序列化
with open('user4.pkl','rb')as f:
res=pickle.load(f)
print(res)
{'name': 'sudada', 'age': 18}
十四、hash模块
14.1、什么是hash?
hash是一种算法,该算法是用来校验文件内容
14.2、hash算法的三大特点
1、只要校验的文本内容一样,那得到的hash值也一样。
2、只要使用hash算法固定,无论校验的内容有多大,得到的hash值的长度都是固定的
3、hash值不可逆(无法通过hash值反解成明文),将明文转换成密文进行传输(把明文密码变成密文传输)
14.3、如何使用hash?
简单了解如何使用:
1、建造一个hash工厂
2、update接收的数据类型都必须是bytes类型
3、最后使用m.hexdigest()得到hash值
import hashlib
m=hashlib.md5() # 建造一个hash工厂
m.update(b'hello') # update接收的数据类型都必须是bytes类型
m.update(b'world')
m.update(b'sudaa')
# hash的值合起来为: b'helloworldsudaa'
print(m.hexdigest()) # 最后使用m.hexdigest()得到hash值
# f10c2a3d06ba5d07becde825224d97b1
14.4、对一个大文件(a.mp4)做hash --使用方式一
方式一:打开文件后,一行行读取内容,最后使用m.hexdigest()拿到hash值
import hashlib
m=hashlib.md5()
with open('a.mp4','rb')as f:
for line in f:
m.update(line)
print(m.hexdigest())
# 9be361df7bfdd8637423d81bd7bce0ef
方式二:直接读取所有的文件内容,使用m.hexdigest()拿到hash值 (二者得到的hash值是一样的)
import hashlib
m=hashlib.md5()
with open('a.mp4','rb')as f:
m.update(f.read())
print(m.hexdigest())
# 9be361df7bfdd8637423d81bd7bce0ef
14.5、将明文密码加密 --为了防止通过撞库的破解方式,需要给密码加盐
import hashlib
passwd='sudada123456'
m=hashlib.md5()
m.update('天王盖地虎'.encode('utf-8'))
m.update(passwd.encode('utf-8'))
m.update('宝塔镇河妖'.encode('utf-8'))
res=m.hexdigest()
print(res)
# 2a1d46c970520ff47261c1a0b0a58f04
十五、正则模块re
1、什么是正则?
正则就是用一些具有特殊含义的符号组合到一起(称为正则表达式)来描述字符或者字符串的方法。(在Python中)它内嵌在Python中,并通过 re 模块实现。
2、常用匹配模式(元字符)
3、正则模块常用实践操作例子
1、' \w ' 匹配字母数字及下划线
import re
# '\w' 匹配的规则(匹配哪些字符)
# 'ab_123 4_c\n\t' 对哪些内容做匹配
res=re.findall('\w','ab_123 4_c\n\t')
print(res)
# 拿到的数据放在一个列表里面。
['a', 'b', '_', '1', '2', '3', '4', '_', 'c']
2、'\W' 匹配非字母数字及下划线
import re
print(re.findall('\W','ab_123 4_c\n\t'))
# [' ', '\n', '\t']
3、'\s' 匹配任意空白字符,包含[\t,\n,\r,\f],只要有'\t,\n,\r,\f'都会被匹配到。
import re
print(re.findall('\s','ab_123 4_c\n\t'))
# [' ', ' ', '\n', '\t']
4、'\s\s' 同时匹配两个任意空白字符
import re
print(re.findall('\s\s','ab_123 4_c\n\t'))
# [' ', '\n\t']
5、'\S' 匹配任意非空字符
import re
print(re.findall('\S','ab_123 4_c\n\t'))
# ['a', 'b', '_', '1', '2', '3', '4', '_', 'c']
6、'\S\S\S'匹配3个连续的非空字符
import re
print(re.findall('\S\S\S','ab_123 4_c\n\t'))
# ['ab_', '123', '4_c']
7、'^aaa' 匹配以aaa开头的内容
import re
# print(re.findall('^aaa','aaa name is aaa,aaa is sb'))
# ['aaa']
8、'aaa$' 匹配以aaa结尾的内容
import re
print(re.findall('sb$','aaa name is aaa,aaa is sb'))
# ['sb']
9、'\n' '\t' 分别只匹配'\n'和'\t' 的字符
import re
print(re.findall('\n','ab_123 4_c\n\t'))
# ['\n']
print(re.findall('\t','ab_123 4_c\n\t'))
# ['\t']
重复匹配字符: . ? * + {m,n}
10、' . ' 匹配任意字符,除了换行符(\n),怎样才能匹配到换行符(\n)呢,需要用到re.DOTALL
import re
# 重复匹配: . ? * + {m,n}
print(re.findall('a.c','123 123a1c xixi a2c a\nc aaaaaac a-c a*c',re.DOTALL))
# ['a1c', 'a2c', 'a\nc', 'aac', 'a-c', 'a*c']
11、 ' ? ' 表示左侧的字符出现0个或者1个
import re
print(re.findall('ab?','a ab abb abbbb abbbbbbbb bbbbba123a'))
# ['a', 'ab', 'ab', 'ab', 'ab', 'a', 'a']
#ab?的匹配规则是:以a开头,b结尾的(不包含中间的值),或者只有a开头的。
12、' * ' 表示左侧的字符出现0个或者无数个
import re
print(re.findall('ab*','a ab abb abbbb abbbbbbbb bbbbba123a'))
# ['a', 'ab', 'abb', 'abbbb', 'abbbbbbbb', 'a', 'a']
#ab*的匹配规则是:以a开头,b结尾的(包含中间所有的),或者只有a开头的。
13、' + ' 表示左侧的字符有1个或者无数个,并且左侧的字符都必须存在
import re
print(re.findall('ab+','a ab abb abbbb abbbbbbbb bbbbba123a'))
# ['ab', 'abb', 'abbbb', 'abbbbbbbb']
#ab+的匹配规则是:ab必须都存在。
14、' {m+n} ' 表示左侧的字符有m到n个
import re
print(re.findall('ab{2,4}','a ab abb abbbb abbbbbbbb bbbbba123a'))
# ['abb', 'abbbb', 'abbbb']
#ab{2,4}的匹配规则是:以a开头,b结尾,其中{2,4}只针对b生效,也就是说:最少取2个b,最多取4个b。
例子2:
print(re.findall('a{2,4}b','aab aaaaab abb abbbb abbbbbbbb bbbbba123a'))
# ['aab', 'aaaab']
#a{2,4}b的匹配规则是:以a开头,b结尾,其中{2,4}只针对a生效,也就是说:最少取2个a,最多取4个a。
例子3:
print(re.findall('ab{2,}','aab aaaaab abb abbbb abbbbbbbb bbbbba123a'))
# ['abb', 'abbbb', 'abbbbbbbb']
#ab{2,}b的匹配规则是:以a开头,b结尾,其中{2,}表示:b最少取2个,最多可以取无数个。
15、用{m,n}的形式可以把 ? * + 都给替代了
import re
例子一:用{0,1}替代? ab? == ab{0,1}
print(re.findall('ab?','aab aaaaab abb abbbb abbbbbbbb bbbbba123a'))
# ['a', 'ab', 'a', 'a', 'a', 'a', 'ab', 'ab', 'ab', 'ab', 'a', 'a']
print(re.findall('ab{0,1}','aab aaaaab abb abbbb abbbbbbbb bbbbba123a'))
# ['a', 'ab', 'a', 'a', 'a', 'a', 'ab', 'ab', 'ab', 'ab', 'a', 'a']
例子二:用{0,}替代* ab* == ab{0,}
print(re.findall('ab*','aab aaaaab abb abbbb abbbbbbbb bbbbba123a'))
# ['a', 'ab', 'a', 'a', 'a', 'a', 'ab', 'abb', 'abbbb', 'abbbbbbbb', 'a', 'a']
print(re.findall('ab{0,}','aab aaaaab abb abbbb abbbbbbbb bbbbba123a'))
# ['a', 'ab', 'a', 'a', 'a', 'a', 'ab', 'abb', 'abbbb', 'abbbbbbbb', 'a', 'a']
例子三:用{1,}替代+ ab+ == ab{1,}
print(re.findall('ab+','aab aaaaab abb abbbb abbbbbbbb bbbbba123a'))
# ['ab', 'ab', 'abb', 'abbbb', 'abbbbbbbb']
print(re.findall('ab{1,}','aab aaaaab abb abbbb abbbbbbbb bbbbba123a'))
# ['ab', 'ab', 'abb', 'abbbb', 'abbbbbbbb']
16、' .* ' 贪婪匹配,与 ' .*? ' 非贪婪匹配
import re
print(re.findall('a.*c','a123123123123123123c123123123123123c'))
# ['a123123123123123123c123123123123123c']
#a.*c 的匹配规则是:以a开头,b结尾,匹配中间的所有内容,无论是否有隔断。
print(re.findall('a.*?c','a123123123123123123c123123123123123c'))
# ['a123123123123123123c']
#a.*?c 的匹配规则是:以a开头,b结尾,匹配中间的所有内容,只取匹配到的第一段。
17、分组 () 与或 |
import re
print(re.findall('compan(ies|y)','companies and company'))
# ['ies', 'y']
#compan(ies|y)默认只取组内的结果,也就是只能取到ies或者y。
print(re.findall('compan(?:ies|y)','companies and company'))
# ['companies', 'company']
#compan(?:ies|y)就是把匹配到内容都取出来,而不是只保留组内的结果
18、取字符串里面的URL,使用 ' (.*?) '
import re
print(re.findall('a href="(.*?)"',
'<a href="https://www.baidu.com"><a href="http://www.baidu.com">'))
# ['https://www.baidu.com', 'http://www.baidu.com']
19、[ ] 匹配一个字符,但是这个字符需要在写 [ ] 内
import re
print(re.findall('a[+]c','abc a-c a+c a*c a1c a2c')) #单个使用
# ['a+c']
print(re.findall('a[+0-9]c','abc a-c a+c a*c a1c a2c')) #组合使用不需要分隔符
# ['a+c', 'a1c', 'a2c']
#在[]内'-'表示的是范围,如果要是有'-',那么就要使用转译\-
#0-9表示:匹配任意数字
#a-z表示:匹配任意小写字母
#A-Z表示:匹配任意大写字母
在[ ] 内转译字符的方法:
import re
print(re.findall('a[\+\-\*\/]c','abc a-c a+c a*c a/c a2c'))
# ['a-c', 'a+c', 'a*c', 'a/c']
在[ ] 内匹配多个数字的写法:[0-9][0-9]表示匹配2为数字,[0-9]*表示匹配任意数字,无论多少位。
import re
print(re.findall('a[0-9][0-9]c','a11c a-c a+c a*c a1c a2c'))
# ['a11c']
print(re.findall('a[0-9]*c','a23111c a-c a+c a*c a1c a2c'))
# ['a23111c', 'a1c', 'a2c']
20、re.search 可以判断匹配的值是否存在,若存在返回一个对象,若不存在则返回None
import re
print(re.search('e','a b c d e f g'))
# <_sre.SRE_Match object; span=(8, 9), match='e'>
#如果能够匹配到'e',那么就返回一个对象
print(re.search('aa','a b c d e f g'))
# None
#如果不能够匹配到'e',那么就返回None
如果想要re.search向re.findall那样匹配某一个值的话,需要在re.search后面加一个.group
import re
print(re.search('e','a b c d e f g').group())
# e
21、re.match('a') 等同于re.search('^a')
import re
print(re.search('^a','a b c d e f g').group())
print(re.match('a','a b c d e f g').group())
# a
# a
22、re.sub 替换: re.sub('Today','Yesterday') 把Today替换成Yesterday
import re
print(re.sub('Today','Yesterday','Today is Monday'))
'Today' # 替换的值
'Yesterday' # 被替换的对象
'Today is Monday' # 对什么做替换
>>: Yesterday is Monday