标签(空格分隔): pythonpython
- 在计算机程序开发的过程当中,随着程序代码越写越多,在一个文件里代码就会愈来愈长,愈来愈不容易维护,为了编写可维护的代码,咱们把不少函数分组,分别放到不一样的文件里面,这样每一个文件里面包含的代码就相对较少了,不少的编程语言都采用这种组织代码的方式,在python中,一个.py文件就是一个模块;
- 1.最大的好处就是大大提升了代码的可维护性,其次,编写代码没必要从零开始,当一个模块编写完毕了,就能够被其余的模块引用,咱们在编写程序的时候,也常常引用其余的模块,包括python 内置模块和来自第三方的模块,
2.使用模块能够避免函数名和变量的冲突,每一个模块有独立的命名空间,所以相同名字的函数和变量彻底能够分别在不一样的模块中,因此,咱们本身在编写模块时,没必要考虑名字会与其余的模块的冲突;
模块分为3类:
1.内置标准模块,又称为:标准库,执行(help'modules')查看全部的python自带模块列表;
2.第三方开源模块,可经过pip install 模块名,联网安装;
3.自定义模块;linux
import module from module import xx from module.xx.xx import xx as rename from module.xx.xx import *
- 注意:模块一旦被调用,即至关于执行了另一个py文件里面的代码;
这个最简单,建立一个.py文件,就能够称之为模块,就能够在另外一个程序里面导入了;git
pip install xx
- 在平时的代码中,咱们经常使用须要和时间打交道,在Python中与时间打交道的就是:time,datetime,calendar(不多用)下面分别来介绍:
在python中一般有这几种方式来表示时间:
1.时间戳
2.格式化时间字符串
3.元组(struct_time)共九个元素,因为python的time模块实现主要调用C库,因此各个平台可能有所不一样;web
1.UTC(Coordinated Universal Time,世界协调时)亦即格林威治天文时间,世界标准时间。在中国为UTC+8。DST(Daylight Saving Time)即夏令时。算法
2.时间戳(timestamp)的方式:一般来讲,时间戳表示的是从1970年1月1日00:00:00开始按秒计算的偏移量。咱们运行“type(time.time())”,返回的是float类型。shell
3.元组(struct_time)方式:struct_time元组共有9个元素,返回struct_time的函数主要有gmtime(),localtime(),strptime()。下面列出这种方式元组中的几个元素:数据库
- time.localtime([secs]):将一个时间戳转换为当前时区的struct_time,secs参数未提供,则以当前时间为准;
import time print(time.localtime())
执行结果:time.struct_time(tm_year=2018, tm_mon=6, tm_mday=25, tm_hour=22, tm_min=13, tm_sec=35, tm_wday=0, tm_yday=176, tm_isdst=0)编程
a=time.localtime() b='%s-%s-%s'%(a.tm_year,a.tm_mon,a.tm_mday) print(b)
执行结果:
'2018-6-25'json
- time.gmtime([secs]):和localtime()方法相似,gmtime()方法是将一个时间戳转换为UTC时区(0时区)的struct_time。
a=time.gmtime() print(a)
执行结果:
time.struct_time(tm_year=2018, tm_mon=6, tm_mday=25, tm_hour=14, tm_min=19, tm_sec=40, tm_wday=0, tm_yday=176, tm_isdst=0)
方法不传值,默认打印的是当前的时间;
以下的代码c#
a=time.localtime(14700032232) print(a)
执行结果:会有对应的时间打印出来
- time.time():返回当前时间的时间戳
- time.mktime():将一个struct_time转化为时间戳
- time.sleep(secs):线程推迟指定的时间运行,单位为秒
- tiem.asctime([t]):把一个时间的元组或者struct_time表示为这种形式:sun oct 1 12:04:38 2017,若是没有参数,将会将time.localtime()做为参数传入;
- time.ctime([secs]):把一个时间戳(秒)转化为time.asctime()的形式,若是参数未给,或者为None的时候,将会默认time.time()做为参数,他的做用至关于time.asctime(time.localtime(secs))
- time.strftime(format[,t]):把一个表明时间的元组或者struct_time(如由time.localtime()和time.gmtime()返回)转化为格式化的时间字符串,若是t未指定,将会传入,time.localtime()
time.strftime('2017-8') time.strftime('%Y-%m-%d %H:%M:%S',) time.strftime('%Y-%m-%d %H:%M:%S %p',)#上午下午 time.strftime('%Y-%m-%d %H:%M:%S %U',)#这个一年的多少周 time.strftime('%Y-%m-%d %H:%M:%S %w',)#这个是周几
相对于time模块,datetime模块的接口直观,更加容易调用;
datetime模块定义了以下的几个类:
- datetime.date:表示日期的类,经常使用的属性有:year month,day
- datetime.time:表示时间的类,经常使用的属性有:hour,minute,second,microsecond
- datetime.datetime :表示日期时间
- datetime.timedelta:表示时间间隔,即两个时间点之间的长度
- datetime.tzinfo 与时区有关的相关信息,(这里再也不赘述,有兴趣的同窗自行查看)
1.d=datetime.datetime.now()返回当前的datetime日期类型
import datetime d=datetime.datetime。now() print(d) print(d.year) print(d.today()) print(d.timestamp()) print(d.timetuple())
等方法能够调用
2.datetime.formtimestamp(322222)把一个时间戳转换为datetime 日期类型;
datetime.date.fromtimestamp(time.time())
3.时间运算:
datetime.datetime.now()+datetime.timedelta(4)#当前时间+4天 datetime.datetime.now()+datetimetimedelta(hours=4)#当前时间+4小时
4.时间的替换
d=datetime.datetime.now() d.replace(year=2999,month=11,day=30) datetime.date(2999,11,30)
程序中有不少的地方须要用到随机字符,好比登陆网站的验证码,经过random模块能够很容易的生成随机字符串
random.randrange(1,10)#返回1-10之间的一个随机数,不包括10 random.randint(1,10)#返回1-10之间的一个随机数,包括10 random.randrange(0,100,2)#随机取0到100之间的偶数 random.random()#返回一个随机浮点数 random.choice('abc#$@1')#返回一个给定数据集合中的随机字符 random.sample('abcdefghij',3)#从多个字符串中选取特定数量的字符
#生成随机的字符串 import string ''.json(random.sample(string.ascii_lowercase+string.digits,6)) #洗牌 a=[0,1,2,3,4,5,6,7,8,9] random.shuffle(a) print(a)
1.获得当前的工做路径,即当前python脚本工做的路径:os.getcwd(),注意这里是python解释器的路径,不是你.py文件的路径
import os print(os.getcwd())
2.返回指定目录下的全部文件和目录名:os.listdir()
#返回当前目录下的全部文件和目录名 print(os.listdir('.'))
3.函数用来删除一个文件:os.remove()
4.删除多个目录:os.removedirs()
os.removedirs(r"c:\python")
5.检验给出的路径是否是一个文件:os.path.isfile()
返回值是true or false
6.检验给出的路径是不是一个目录:os.path.isdir()
返回值是true or false
7.判断是不是绝对路径:os.path.exists()
返回是true or false
8.返回一个路径的目录名和文件名:os.path.split()
os.path.split('/home/haha/lele/test.txt')
执行结果是:
('/home/haha/lele/','test.txt')
9.分离扩展名:os.path.splitext()
os.path.splittext('/home/haha/lele/test.txt')
执行结果:('/home/haha/lele/test','.py')
10.获取路径名字:os.path.dirname()
11.获取绝对路径:os.path.abspath()
12.获取文件名:os.paht.basename()
13.运行shell命令:os.system()
os.system('df-h')#查看磁盘
14.读取操做系统环境变量HOME的值:os.getenv('HOME')
15.返回操做系统全部的环境变量的值:os.environ
16.设置环境变量,仅仅程序运行的时候有效果:
os.environ.setdefault('HOME','/home/mimi')
17.给出当前平台使用的终止符:os.linesep
- windwos 使用的是:'\r\n',Linux使用的是:'\n',mac使用的是'\r'
18.指出你正在使用的平台:os.name
- windows 使用的是:'nt',而对于linux用户,他是:'posix'
19.重命名:os.rename(old_name,new_name)
20.建立多级目录:os.makedirs(r'c:\python\test')
21.建立单个目录:os.mkdir('test')
22.获取文件的属性:os.stat(file)
23.终止当前进程:os.exit()
24.获取文件的大小:os.path.getsize(filename)
25.修改文件的权限和时间戳:os.chmod(file)
26.结合目录和文件名:os.path.join(dir,filename)
27.改变工做目录到dirname:os.chdir(dirname)
28.获取当前终端的大小:os.get_terminal_size()
29.杀死进程:os.kill(10884,signal.SIGKILL)
1.sys.argv
python3 test.py run web
执行结果:
['test.py','run','web']
这个意思就是有的脚本后边能够跟参数,若是跟run咱们就执行run,若是跟web 咱们就执行web
2.sys.exit(n)退出程序,正常退出
3.sys.version 获取当前解释器的版本
4.sys.maxint 最大的Int值
5.sys.path 返回模块的搜索路径,初始化时使用PYTHONPATH环境变量的值
6.sys.platform 返回操做平台的名称
7.sys.getrecursionlimit()获取递归的最大层数
8.sys.setrecursionlimit(1200) 设置最大递归层数
9.sys.getdefaultencoding() 获取解释器默认编码
10.sys.getfilesystemencoding 获取内存数据存到文件里的默认编码
高级的文件,文件夹,压缩包处理模块
- shutil.copyfileobj(fsrc,fdst[,llength])
将文件内容拷贝到另外一个文件中,能够部份内容
源码以下:
def copyfileobj(fsrc, fdst, length=16*1024):#这里是每次读多少,并非拷贝多少长度 """copy data from file-like object fsrc to file-like object fdst""" while 1: buf = fsrc.read(length)#这里是每次读多少,并非拷贝多少长度 if not buf: break fdst.write(buf)
演示:
新建一个文件叫sheve_test.py,内容以下图所示并保存:
import shutil f1=open("sheve_test.py",'r') f2=open("sheve_test_new.py",'w') shutil.copyfileobj(f1,f2)
而后新建一个.py文件用来编写脚本,copy文件的
import shutil f1=open("sheve_test.py",'r') f2=open("sheve_test_new.py",'w') shutil.copyfileobj(f1,f2)
如上述代码执行完毕后,会生成一个文件:sheve_test_new.py文件,在这个文件里面,会有和sheve_test.py文件同样的内容;如上图文件;
- shutil.copyfile(src, dst)
拷贝文件
源码以下:
def copyfile(src, dst): """Copy data from src to dst""" if _samefile(src, dst): raise Error("`%s` and `%s` are the same file" % (src, dst)) for fn in [src, dst]: try: st = os.stat(fn) except OSError: # File most likely does not exist pass else: # XXX What about other special files? (sockets, devices...) if stat.S_ISFIFO(st.st_mode): raise SpecialFileError("`%s` is a named pipe" % fn) with open(src, 'rb') as fsrc: with open(dst, 'wb') as fdst: copyfileobj(fsrc, fdst)
- shutil.copymode(src, dst)
仅拷贝权限。内容、组、用户均不变
源码以下:
def copymode(src, dst): """Copy mode bits from src to dst""" if hasattr(os, 'chmod'): st = os.stat(src) mode = stat.S_IMODE(st.st_mode) os.chmod(dst, mode)
- shutil.copystat(src, dst)
拷贝状态的信息,包括:mode bits, atime, mtime, flags
源码以下:
def copystat(src, dst): """Copy all stat info (mode bits, atime, mtime, flags) from src to dst""" st = os.stat(src) mode = stat.S_IMODE(st.st_mode) if hasattr(os, 'utime'): os.utime(dst, (st.st_atime, st.st_mtime)) if hasattr(os, 'chmod'): os.chmod(dst, mode) if hasattr(os, 'chflags') and hasattr(st, 'st_flags'): try: os.chflags(dst, st.st_flags) except OSError, why: for err in 'EOPNOTSUPP', 'ENOTSUP': if hasattr(errno, err) and why.errno == getattr(errno, err): break else: raise
- shutil.copy(src, dst)
拷贝文件和权限
源码以下:
def copy(src, dst): """Copy data and mode bits ("cp src dst"). The destination may be a directory. """ if os.path.isdir(dst): dst = os.path.join(dst, os.path.basename(src)) copyfile(src, dst) copymode(src, dst
- shutil.copy2(src, dst)
拷贝文件和状态信息
源码以下:
def copy2(src, dst): """Copy data and all stat info ("cp -p src dst"). The destination may be a directory. """ if os.path.isdir(dst): dst = os.path.join(dst, os.path.basename(src)) copyfile(src, dst) copystat(src, dst)
- shutil.ignore_patterns(*patterns)
shutil.copytree(src, dst, symlinks=False, ignore=None)
递归的去拷贝文件
例如:copytree(source, destination, ignore=ignore_patterns('.pyc', 'tmp'))
- shutil.rmtree(path[, ignore_errors[, onerror]])
递归的去删除文件
- shutil.move(src, dst)
递归的去移动文件
序列化,是指吧内存里的数据类型转化成为字符串,以使其能存储到硬盘或者经过网络传输到远程,由于硬盘或者网络传输之恩可以接受bytes
你打游戏的时候,打累了,休息了2天,关掉游戏,结果你下次开始仍是从你上次的地方接着打,那么你上次玩游戏的进度确定是存在硬盘上了,是以何种形式呢?
游戏过程当中产生的不少临时数据是不规律的,可能在你关掉,游戏的时候正好有10个列表,3个嵌套字典数据,集合在内存里面,须要存下来,你如何存呢?把列表变成文件里的多行多列的形式?那嵌套字典呢?根本没办法存,因此,如果有种办法能够直接把内存数据存到硬盘上,下次程序启动,在从硬盘上读回来,仍是原来的格式化,天然是极好的办法;
- 用于序列化的两个模块:
json,用于字符串和python数据类型间进行转换;
pickle,用于python特有的类型和python的数据类型间进行转换;
data = {'roles': [ {'role': 'monster', 'type': 'pig', 'life': 50}, {'role': 'hero', 'type': '关羽', 'life': 80}, ]} f = open("game_status", 'w') f.write(data)
执行结果:
Traceback (most recent call last):
File "G:/fancy/misc/shuiltdemo.py", line 8, in
f.write(data)
TypeError: write() argument must be str, not dict
Process finished with exit code 1
报错了,信息显示必需要接收str类型;
data = {'roles': [ {'role': 'monster', 'type': 'pig', 'life': 50}, {'role': 'hero', 'type': '关羽', 'life': 80}, ]} f = open("game_status", 'w') f.write(str(data))
执行以上结果就ok了不会报错了;
- 紧接着上述的步骤走:
把建立的game_status文件的内容读出来:
f = open("game_status",'r') d=f.read() print(d['roles'])
执行结果:
Traceback (most recent call last):
File "G:/fancy/misc/shuiltdemo.py", line 12, in
print(d['roles'])
TypeError: string indices must be integers
结果报错,由于d是str类型的
这里就须要咱们把str变为字典,那咱们采起以下的手段:
d=dict(d)
执行结果:
d=dict(d)
ValueError: dictionary update sequence element #0 has length 1; 2 is required
结果仍是不行;
- 如上的问题就是字典转成字符串,在反转就转不会来了,这就是这个问题,那咱们怎么办呢?
- 这里咱们以前学过:eval()
f = open("game_status",'r') d=f.read() d=eval(d) print(d['roles'])
执行结果为:
[{'role': 'monster', 'type': 'pig', 'life': 50}, {'role': 'hero', 'type': '关羽', 'life': 80}]
- 把内存数据转成字符,叫作序列化
把字符转成内存数据,叫作反序列化;
刚刚的代码作了两件事情:1.是把字典变成字符串,2.是把字符串eval()一下,转换为内存数据;
- 其实在python里面有自带的模块专门干这个功能的;
1.pickle 模块
2.json 模块
这两个模块的主要功能就是内存的数据很容易存下来,也很容易读出来;
这两个模块的用法彻底同样;
- json:
1.dumps()
import json data = {'roles': [ {'role': 'monster', 'type': 'pig', 'life': 50}, {'role': 'hero', 'type': '关羽', 'life': 80}, ]} d=json.dumps(data)# print(d,type(d))
执行结果:
{"roles": [{"role": "monster", "type": "pig", "life": 50}, {"role": "hero", "type": "\u5173\u7fbd", "life": 80}]} <class 'str'>
如上结果能够看出,他已是个字符串了;
2.dump()
这个和dumps()其实差很少,只是dumps()只传入数据的参数,可是dump()要传入数据和文件;
import json data = {'roles': [ {'role': 'monster', 'type': 'pig', 'life': 50}, {'role': 'hero', 'type': '关羽', 'life': 80}, ]} json.dump(data,'test.json')#仅仅转成字符串
执行结果:
AttributeError: 'str' object has no attribute 'write'
报错了,
- 这里申明一下:dump()在传入文件的时候,文件要是一个能够写的对象,由于他不能本身打开文件;
import json data = {'roles': [ {'role': 'monster', 'type': 'pig', 'life': 50}, {'role': 'hero', 'type': '关羽', 'life': 80}, ]} f = open("test.json",'w')#增长些的权限,而且打开不文件 json.dump(data,f)#转成字符串并写入文件
如上述,执行结果不会报错了,正常出现了test.json文件
- loads()
import json data = {'roles': [ {'role': 'monster', 'type': 'pig', 'life': 50}, {'role': 'hero', 'type': '关羽', 'life': 80}, ]} d=json.dumps(data) d2=json.loads(d) print(d2['roles'])
执行结果:
[{'role': 'monster', 'type': 'pig', 'life': 50}, {'role': 'hero', 'type': '关羽', 'life': 80}]
*load()
如下例子是打开刚刚生成的json文件
f =open('test.json','r') data=json.load(f) print(data)
执行结果为:
{'roles': [{'role': 'monster', 'type': 'pig', 'life': 50}, {'role': 'hero', 'type': '关羽', 'life': 80}]}
1.把数据类型转化为字符串存到内存的意义?
json.dumps json.loads
a.把你的内存数据,经过网络,共享给远程其它人;
b.能够跨平台,跨语言共享你的数据;
c.定义了不一样语言的以前的交互规则
纯文本:坏处:不能共享给远程其余的人;
xml:坏处:占用的空间大
json:简单,可读性好
- 刚才我只是把这个数据dumps()了一次,能不能dump()屡次呢?
答案:
是能够的;这里你们自行实验;
那能够对于dump()屡次的,能够load()吗?,能够load()屡次吗
答案:
在load()的时候会报错的,load()一次就会报错,load()屡次也会报错的;
- 这里注意,dump()了几回,而后,load()第一次就会报错,因此,咱们在使用dump()和load()的时候不要反复的dump()和load()
总结:
json:的方法:
dumps()------------loads()
dump()--------------load()
pickle和json的用法是一致的:
例子:以下代码:
import pickle d = {'name': 'alex', 'age': 22} l = [1, 2, 3, 'rain'] pk = open('data.pkl','w') print(pickle.dumps(d))
执行结果:
b'\x80\x03}q\x00(X\x04\x00\x00\x00nameq\x01X\x04\x00\x00\x00alexq\x02X\x03\x00\x00\x00ageq\x03K\x
它会先转化为bytes类型;
import pickle d = {'name': 'awaw', 'age': 22} l = [1, 2, 3, 'rain'] pk = open('data.pkl', 'wb') pickle.dump(d, pk)
那么反序列化呢:
f=open('data.pkl','rb') d=pickle.load(f) print(d)
打开上图的文件,而后进行load()就能够了
执行结果为:
{'name': 'awaw', 'age': 22}
- json 和pickle的区别呢?
json:支持:str int,tuple,list,dict,不支持set
pickle:支持:python里面的全部的数据类型,包括函数;
2.这样说来,pickle更牛逼,咱们之后就用pickle好了;
答案不行:
pickle之能在python里面用,不能跨平台,跨语言;(因此说没用不用研究)
以前说json和pickle只能dump,load一次,假如我确实有好几种数据须要序列化,若是只能dump一次的话,这就意味着我本身要dump好几个文件,这个时候就感受很low,难道没有办法容许我dump好几回吗?
shelve他是对pickle的封装,容许你dump屡次,load屡次,而且不会顺序乱,由于他是一种key-value的形式;(这个下去本身研究,这里不在多说了,由于它主要是对pickle封装的)
不少软件都有配置文件,来配置一些参数;
编写一个配置文件叫:conf.ini
内容以下:
[DEFAULT] ServerAliveInterval =45 Compression = yes CompressionLevel = 9 ForwardX11 = yes [bitbucket.org] User = hg [topsecret.server.com] Port=50022 ForwardX11 = no
而后进行以下的操做:
import configparser conf=configparser.ConfigParser() # print(conf.sections()) conf.read('conf.ini') print(conf.default_section)#打印配置文件的deaulf print(dir(conf["bitbucket.org"]))#打印bitbucket.org的值 for k,v in conf["bitbucket.org"].items(): print(k,v)#这时候default的内容也会展现出来,默认default会在后续的节点都会展现出来
增删改查,本身行研究;
在讲解这个模块以前先给你们说一些,关于加密的一些知识:
HASH
- Hash,通常翻译作“散列”,也有直接音译为”哈希”的,就是把任意长度的输入(又叫作预映射,pre-image),经过散列算法,变换成固定长度的输出,该输出就是散列值。这种转换是一种压缩映射,也就是,散列值的空间一般远小于输入的空间,不一样的输入可能会散列成相同的输出,而不可能从散列值来惟一的肯定输入值。
- 简单的说就是一种将任意长度的消息压缩到某一固定长度的消息摘要的函数。
- HASH主要用于信息安全领域中加密算法,他把一些不一样长度的信息转化成杂乱的128位的编码里,叫作HASH值.也能够说,hash就是找到一种数据内容和数据存放地址之间的映射关系
- 输入任意长度的信息,通过处理,输出为128位的信息(数字指纹);不一样的输入获得的不一样的结果(惟一性);
- MD5算法的特色
1.压缩性:任意长度的数据,算出的MD5值的长度都是固定的
2.容易计算:从原数据计算出MD5值很容易
3.抗修改性:对原数据进行任何改动,修改一个字节生成的MD5值区别也会很大
4.强抗碰撞:已知原数据和MD5,想找到一个具备相同MD5值的数据(即伪造数据)是很是困难的。
- MD5不可逆的缘由是其是一种散列函数,使用的是hash算法,在计算过程当中原文的部分信息是丢失了的。
1.防止被篡改:
好比发送一个电子文档,发送前,我先获得MD5的输出结果a。而后在对方收到电子文档后,对方也获得一个MD5的输出结果b。若是a与b同样就表明中途未被篡改。
好比我提供文件下载,为了防止不法分子在安装程序中添加木马,我能够在网站上公布由安装文件获得的MD5输出结果。
SVN在检测文件是否在CheckOut后被修改过,也是用到了MD5.
2.防止直接看到明文:
如今不少网站在数据库存储用户的密码的时候都是存储用户密码的MD5值。这样就算不法分子获得数据库的用户密码的MD5值,也没法知道用户的密码。(好比在UNIX系统中用户的密码就是以MD5(或其它相似的算法)经加密后存储在文件系统中。当用户登陆的时候,系统把用户输入的密码计算成MD5值,而后再去和保存在文件系统中的MD5值进行比较,进而肯定输入的密码是否正确。经过这样的步骤,系统在并不知道用户密码的明码的状况下就能够肯定用户登陆系统的合法性。这不但能够避免用户的密码被具备系统管理员权限的用户知道,并且还在必定程度上增长了密码被破解的难度。)
3.防止抵赖:(数字签名)
这须要一个第三方认证机构。例如A写了一个文件,认证机构对此文件用MD5算法产生摘要信息并作好记录。若之后A说这文件不是他写的,权威机构只需对此文件从新产生摘要信息,而后跟记录在册的摘要信息进行比对,相同的话,就证实是A写的了。这就是所谓的“数字签名”。
安全哈希算法(Secure Hash Algorithm)主要适用于数字签名标准(Digital Signature Standard DSS)里面定义的数字签名算法(Digital Signature Algorithm DSA)。对于长度小于2^64位的消息,SHA1会产生一个160位的消息摘要。当接收到消息的时候,这个消息摘要能够用来验证数据的完整性。
SHA是美国国家安全局设计的,由美国国家标准和技术研究院发布的一系列密码散列函数。
因为MD5和SHA-1于2005年被山东大学的教授王小云破解了,科学家们又推出了SHA224, SHA256, SHA384, SHA512,固然位数越长,破解难度越大,但同时生成加密的消息摘要所耗时间也更长。目前最流行的是加密算法是SHA-256 .
因为MD5与SHA-1均是从MD4发展而来,它们的结构和强度等特性有不少类似之处,SHA-1与MD5的最大区别在于其摘要比MD5摘要长32 比特。对于强行攻击,产生任何一个报文使之摘要等于给定报文摘要的难度:MD5是2128数量级的操做,SHA-1是2160数量级的操做。产生具备相同摘要的两个报文的难度:MD5是264是数量级的操做,SHA-1 是280数量级的操做。于是,SHA-1对强行攻击的强度更大。但因为SHA-1的循环步骤比MD5多80:64且要处理的缓存大160比特:128比特,SHA-1的运行速度比MD5慢.
用于加密相关的操做,3.x里代替了md5模块和sha模块,主要提供 SHA1, SHA224, SHA256, SHA384, SHA512 ,MD5 算法
import hashlib m = hashlib.md5() m.update(b"Hello") m.update(b"It's me") print(m.digest()) m.update(b"It's been a long time since last time we ...") print(m.digest()) #2进制格式hash print(len(m.hexdigest())) #16进制格式hash ''' def digest(self, *args, **kwargs): # real signature unknown """ Return the digest value as a string of binary data. """ pass def hexdigest(self, *args, **kwargs): # real signature unknown """ Return the digest value as a string of hexadecimal digits. """ pass ''' import hashlib # ######## md5 ######## hash = hashlib.md5() hash.update('admin') print(hash.hexdigest()) # ######## sha1 ######## hash = hashlib.sha1() hash.update('admin') print(hash.hexdigest()) # ######## sha256 ######## hash = hashlib.sha256() hash.update('admin') print(hash.hexdigest()) # ######## sha384 ######## hash = hashlib.sha384() hash.update('admin') print(hash.hexdigest()) # ######## sha512 ######## hash = hashlib.sha512() hash.update('admin') print(hash.hexdigest())
import hashlib print(hash('wang'))
执行结果为:
3991323452314028184
- 注意只要程序不退出,wang的全部的hash都是这个字符串,一旦退出从新进入程序,从新编译,就不是这样的结果了;
- hash 是不可逆的,即便知道了:3991323452314028184也不能反推出来:wang
因此常被用于各个的加密网站,是加密的基础的东西;
- 咱们常常须要经过Python去执行一条系统命令或脚本,系统的shell命令是独立于你的python进程以外的,每执行一条命令,就是发起一个新进程,经过python调用系统命令或脚本的模块在python2有os.system
import os os.system('uname')
执行结果(小编是Mac):
Darwin
0
这个代码就是执行系统的命令,其中0就是执行的状态,每一个系统都是有状态,Linux就是成功:0,若是是非零就是说明失败;
linux中经过:echo $?能够查看上一个命令执行的一个状态;
import os a=os.sytem('df') print(a)# a=0这里a是上次执行的一个状态;
经过上述的代码我是拿不到os.system('df')输出 的结果的,若是我想拿到怎么办呢?
os.popen('df -h')
执行结果:<os._wrap_close object at 0x103a14588>
至关于在内存里面打开了一个临时文件,把内容存到临时文件里面;so,咱们只须要把这个文件读出来就行了;
import os os.system('df') f=os.popen('df -h') f.read()
so:咱们须要学习subprocess
以前调用操做系统,执行命令的方法不少种,python2也有不少种,例如:commands,python3清理一些不规范的东西,把以前的东西规范化,subsprocess替换了别的,规范化;
- 三种执行命令的方法:
1.subprocess.run(*popenargs, input=None, timeout=None, check=False, **kwargs) #官方推荐 2. subprocess.call(*popenargs, timeout=None, **kwargs) #跟上面实现的内容差很少,另外一种写法 3.subprocess.Popen() #上面各类方法的底层封装
- 执行这个命令,返回一个对象,拿着对象执行命令;
1.标准写法:
subprocess.run(['df','-h'],stderr=subprocess.PIPE,stdout=subprocess.PIPE,check=True)
2.涉及到管道|的命令须要这样写
subprocess.run('df -h|grep disk1',shell=True) #shell=True的意思是这条命令直接交给系统去执行,不须要python负责解析
#执行命令,返回命令执行状态 , 0 or 非0 >>> retcode = subprocess.call(["ls", "-l"]) #执行命令,若是命令结果为0,就正常返回,不然抛异常 >>> subprocess.check_call(["ls", "-l"]) 0 #接收字符串格式命令,返回元组形式,第1个元素是执行状态,第2个是命令结果 >>> subprocess.getstatusoutput('ls /bin/ls') (0, '/bin/ls') #接收字符串格式命令,并返回结果 >>> subprocess.getoutput('ls /bin/ls') '/bin/ls' #执行命令,并返回结果,注意是返回结果,不是打印,下例结果返回给res >>> res=subprocess.check_output(['ls','-l']) >>> res b'total 0\ndrwxr-xr-x 12 alex staff 408 Nov 2 11:05 OldBoyCRM\n'
经常使用参数:
args:shell命令,能够是字符串或者序列类型(如:list,元组)
stdin, stdout, stderr:分别表示程序的标准输入、输出、错误句柄
preexec_fn:只在Unix平台下有效,用于指定一个可执行对象(callable object),它将在子进程运行以前被调用
shell:同上
cwd:用于设置子进程的当前目录
env:用于指定子进程的环境变量。若是env = None,子进程的环境变量将从父进程中继承。
下面这2条语句执行会有什么区别?
a=subprocess.run('sleep 10',shell=True,stdout=subprocess.PIPE)
a=subprocess.Popen('sleep 10',shell=True,stdout=subprocess.PIPE)
区别是Popen会在发起命令后马上返回,而不等命令执行结果。这样的好处是什么呢?
若是你调用的命令或脚本 须要执行10分钟,你的主程序不需卡在这里等10分钟,能够继续往下走,干别的事情,每过一会,经过一个什么方法来检测一下命令是否执行完成就行了。
Popen调用后会返回一个对象,能够经过这个对象拿到命令执行结果或状态等,该对象有如下方法
poll()
Check if child process has terminated. Returns returncode
wait()
Wait for child process to terminate. Returns returncode attribute.
terminate()终止所启动的进程Terminate the process with SIGTERM
kill() 杀死所启动的进程 Kill the process with SIGKILL
communicate()与启动的进程交互,发送数据到stdin,并从stdout接收输出,而后等待任务结束a = subprocess.Popen('python3 guess_age.py',stdout=subprocess.PIPE,stderr=subprocess.PIPE,stdin=subprocess.PIPE,shell=True)
a.communicate(b'22')
(b'your guess:try bigger\n', b'')
send_signal(signal.xxx)发送系统信号
pid 拿到所启动进程的进程号
logging模块就是为了帮助咱们记录日志,记录日志,为了之后分析所用,或者除了问题能够查看;
- python的logging模块提供了标准的日志接口,你能够经过它存储各类格式的日志,logging的日志能够分为: debug(),info(), warning(),error()
and critical()5个级别,下面咱们看一下怎么用?
import logging logging.warning('i am logging 3 times') logging.critical('server down')
执行结果:是输出到屏幕的
WARNING:root:i am logging 3 times
CRITICAL:root:server down
- 看一下日志级别:
import logging logging.basicConfig(filename='example.log',level=logging.INFO) logging.debug('This message shouldn't go to the log file') logging.info('So should this') logging.warning('And this, too')
其中下面这句中的level=loggin.INFO意思是,把日志纪录级别设置为INFO,也就是说,只有比日志是INFO或比INFO级别更高的日志才会被纪录到文件里,在这个例子, 第一条日志是不会被纪录的,若是但愿纪录debug的日志,那把日志级别改为DEBUG就好了
import logging logging.basicConfig(format='%(asctime)s %(message)s', datefmt='%m/%d/%Y %I:%M:%S %p') logging.warning('is when this event was logged.') #输出 12/12/2010 11:46:36 AM is when this event was logged.
除了加时间,还能够自定义一大堆格式,下表就是全部支持的格式:
- 若是一条日志同时向屏幕和文件打印怎么办?
这里咱们须要了解logging模块的复杂知识:
logging有4个主要的类:
1.logger:提供了应用程序直接使用的接口;
2.handler:将logger建立的日志发送到合适的目的地:
3.filter:提供过滤,来决定哪些日志须要输出;
4.formatter决定日志记录的最终输出格式;
他们之间的关系如图:
- 每一个程序在输出信息以前都要得到一个Logger。Logger一般对应了程序的模块名,好比聊天工具的图形界面模块能够这样得到它的Logger:
LOG=loggin.getlogger('chat.gui')
而核心模块能够这样设置:
LOG=logging.getlogger('chat.kernel')
还能够绑定handler和filters:
- Logger.setLevel(lel):指定最低的日志级别,低于lel的级别将被忽略。debug是最低的内置级别,critical为最高
Logger.addFilter(filt)、Logger.removeFilter(filt):添加或删除指定的filter
Logger.addHandler(hdlr)、Logger.removeHandler(hdlr):增长或删除指定的handler
Logger.debug()、Logger.info()、Logger.warning()、Logger.error()、Logger.critical():能够设置的日志级别
- handler对象负责发送相关的信息到指定目的地。Python的日志系统有多种Handler可使用。有些Handler能够把信息输出到控制台,有些Handler能够把信息输出到文件,还有些 Handler能够把信息发送到网络上。若是以为不够用,还能够编写本身的Handler。能够经过addHandler()方法添加多个多handler
- Handler.setLevel(lel):指定被处理的信息级别,低于lel级别的信息将被忽略
Handler.setFormatter():给这个handler选择一个格式
Handler.addFilter(filt)、Handler.removeFilter(filt):新增或删除一个filter对象
每一个Logger能够附加多个Handler。接下来咱们就来介绍一些经常使用的Handler:
- 1.logging.StreamHandler 使用这个Handler能够向相似与sys.stdout或者sys.stderr的任何文件对象(file object)输出信息。
2.logging.FileHandler 和StreamHandler 相似,用于向一个文件输出日志信息。不过FileHandler会帮你打开这个文件
3.logging.handlers.RotatingFileHandler
这个Handler相似于上面的FileHandler,可是它能够管理文件大小。当文件达到必定大小以后,它会自动将当前日志文件更名,而后建立 一个新的同名日志文件继续输出。好比日志文件是chat.log。当chat.log达到指定的大小以后,RotatingFileHandler自动把 文件更名为chat.log.1。不过,若是chat.log.1已经存在,会先把chat.log.1重命名为chat.log.2。。。最后从新建立 chat.log,继续输出日志信息。它的函数是:
- RotatingFileHandler( filename[, mode[, maxBytes[, backupCount]]])
其中filename和mode两个参数和FileHandler同样。
- maxBytes用于指定日志文件的最大文件大小。若是maxBytes为0,意味着日志文件能够无限大,这时上面描述的重命名过程就不会发生。
- backupCount用于指定保留的备份文件的个数。好比,若是指定为2,当上面描述的重命名过程发生时,原有的chat.log.2并不会被改名,而是被删除。
4.logging.handlers.TimedRotatingFileHandler
这个Handler和RotatingFileHandler相似,不过,它没有经过判断文件大小来决定什么时候从新建立日志文件,而是间隔必定时间就 自动建立新的日志文件。重命名的过程与RotatingFileHandler相似,不过新的文件不是附加数字,而是当前时间。它的函数是:
- TimedRotatingFileHandler( filename [,when [,interval [,backupCount]]])
其中filename参数和backupCount参数和RotatingFileHandler具备相同的意义。
interval是时间间隔。
when参数是一个字符串。表示时间间隔的单位,不区分大小写。它有如下取值:
S 秒
M 分
H 小时
D 天
W 每星期(interval==0时表明星期一)
midnight 天天凌晨
日志的formatter是个独立的组件,能够跟handler组合
- fh = logging.FileHandler("access.log")
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
fh.setFormatter(formatter) #把formmater绑定到fh上
class IgnoreBackupLogFilter(logging.Filter): """忽略带db backup 的日志""" def filter(self, record): #固定写法 return "db backup" not in record.getMessage()
filter 返回true或者false,logger 根据这个进行判断是否输出日志;
例如:
import logging #生成logger对象: logger= logging.getLogger('web') logger.setLevel(logging.INFO) #生成hander对象 ch = logging.StreamHandler() ch.setLevel(logging.DEBUG) fh = logging.FileHandler('web.log') fh.setLevel(logging.INFO) #把handler对象绑定logger对象 logger.addHandler(ch) logger.addHandler(fh) #生成formatter对象 #把formatter对象绑定handler对象 file_format= logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') console_format = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') ch.setFormatter(console_format) fh.setFormatter(file_format) logger.debug('test_log') #console:DEBUG #global:INFO(默认级别最高,若是不设置,就是说默认是Warning,就是说默认的就是Warning) #file:Warning
- 问题:如上述所示:全局级别的设置为:INFO,屏幕的为DEBUG,文件的为INFO,这时候直接结果为: 文件有内容,屏幕不输出; 2.若是把全局设置为DEBUG这时候看看:结果如何: 会发现,屏幕的输出了,而文件的没有输出; 3.若是全局的不设置会怎样,: 结果发现,屏幕和文件都没有输出,由于全局的若是不写,默认是Warning,低于Warning都不会输出;