一. 关于hashlib模块的一些注意点
hashlib模块用于加密相关的操作,代替了md5模块和sha模块,主要提供 SHA1, SHA224, SHA256, SHA384, SHA512, MD5 算法;
md5生成一个32位的16进制字符;
SHA1的结果是160 bit字节,通常用一个40位的16进制字符串表示,比SHA1更安全的算法是SHA256和SHA512,不过越安全的算法越慢,切长度更长。
以MD5为例,一般的计算方法如下:
m = hashlib.md5() a = ‘test1‘ m.update(bytes(a, encoding=‘utf-8‘)) # hexdigest是输出的16进制的结果 print(m.hexdigest()) # hexdigest的结果用hex来decode之后得到的就是这个 print(m.digest())
但有的时候我们需要对一个大文件求md5值,这时候就无法将整个文件内容读取进内存,需要类似如下处理:
1 m = hashlib.md5() 2 read_len = 2 ** 16 3 with open(file_path) as f: 4 while True: 5 buf = f.read(read_len) 6 if buf: 7 m.update(buf) 8 else: 9 break 10 print(m.hexdigest())
分段一定长度读取整个文件,然后不断update直到全部结束。
另外需要注意的是,上述的各种摘要算法的结果,都不是唯一的,也就是说不同的字符串可能计算出相同结果,这种被称为碰撞。所以不能将之作为一个唯一键来发挥作用。
二. exec和eval的注意点
exec和eval给我们的感觉很相似,都是动态执行一个字符串,但是他们是有明显区别的。
exec是一个语法,并非函数(即类似if, for之类的),它的作用是将收到的字符串作为py代码动态的运行,因此也就没有返回值。
示例如下:
1 >>> exec("for i in range(5):print i") 2 0 3 1 4 2 5 3 6 4
eval是一个方法,是动态计算作为字符串的表达式的值,会返回表达式的结果;也因此非表达式的语句是无法运行的。
示例如下:
1 # eval无法计算非表达式 2 >>> eval("for i in range(5):print i") 3 Traceback (most recent call last): 4 File "<stdin>", line 1, in <module> 5 File "<string>", line 1 6 for i in range(5):print i 7 ^ 8 SyntaxError: invalid syntax 9 10 11 # 表达式的结果会直接输出 12 >>> eval(‘5 + a‘, {‘a‘:1}) 13 6
三. subprogress模块
subprogress模块用于执行系统命令,类似于os.system, os.spawn*;不过subprogress在现在更推荐,官方文档中说:
可见未来可能会完全抛弃上述两个老的模块。
我写了一个用subprogress.PIPE(本方法适合于执行复杂命令)来执行git clone操作的小方法作为示例如下:
1 def checkout_codes(git_url, tag_version, user_id, passwd, dst_dir): 2 PIPE = subprocess.PIPE 3 git_cmd = "https://%s:%[email protected]%s" % (user_id, passwd, git_url) 4 process = subprocess.Popen([‘git‘, ‘clone‘, git_cmd, dst_dir, ‘-b‘, tag_version], 5 stdout=PIPE, stderr=PIPE) 6 stdoutput, stderroutput = process.communicate() 7 if process.poll(): 8 print stdoutput 9 print stderroutput 10 return False 11 return True
三. configparser模块
onfigparser用于处理特定格式的文件,其本质上是利用open来操作文件。
在python2中configparser库库叫ConfigParse,需要pip来安装
该库实现了操作ini风格类型文件的各种方法。ini风格类型示例如下:
1 [111] 2 password = 222 3 admin_flag = 0 4 5 [222] 6 password = 333 7 admin_flag = 0 8 9 [444] 10 password = 555 11 admin_flag = 1
每个[]代表一个section,下面一个等号对代表这个section的一项属性和值。使用configparser的各种方法示例如下:
1 cf = configparser.ConfigParser() 2 # 读取文件 3 cf.read(‘a.conf‘) 4 5 # sections方法返回所有的section名字的列表 6 for sec in cf.sections(): 7 print(sec) 8 9 10 # 增加一个新的section 11 cf.addsection(‘555‘) 12 # 给新的section‘555‘增加属性 13 set(‘555‘, ‘password‘, ‘3232‘) 14 15 16 # 原有的section的属性也可以更改,和增加的方法一致 17 set(‘444‘, ‘password‘, ‘3232‘) 18 19 # 通过get和getint方法之类可以取到一个section的一个属性的值 20 cf.get(‘444‘, ‘password‘) 21 cf.getint(‘444‘, ‘password‘) 22 23 # 通过items可以获得一个section的所有属性 24 cf.items(‘444‘) 25 26 27 # 更改结束以后,用write修改文件 28 cf.write(open(‘a.conf‘, "w")