Python 18 标准库-configparse hashlib模块

Python 18 标准库-configparse hashlib模块

旧博客Python系列

大部分程序的配置文件比如经常见到的.ini文件,其中都采取类似下面的固定格式:

[DEFAULT]
ServerAliveInterval = 45
Compression = yes
CompressionLevel = 9
ForwardX11 = yes

[bitbucket.org]
User = hg

[topsecret.server.com]
Port = 50022
ForwardX11 = no

其中方括号包含的叫做section name,下边的每一个是一个option 和对应的 value.
configparse模块提供了一种类似字典的对象来对一个配置文件进行操作.section的名字与其下的各个配置就是一个键值对,而各个配置本身也是一个字典,这样就将配置文件解析为一个嵌套的字典对象.

建立config文件对象

# 使用configparser模块下的ConfigParser类实例化一个对象
import configparser
config = configparser.ConfigParser()
实例化之后的config对象,就是一个config结构对象,可以把这个对象理解为带有其他功能的字典,增删改查可以采取字典的形式进行操作,键就是中括号里的section name,值对应的字典就是section内部的设置和值对.config对象也提供了其他的一些方法进行操作.

字典方式操作config对象

config[""DEFAULT""] = {'ServerAliveInterval': '45',
                     'Compression': 'yes',
                     'CompressionLevel': 9}
config['bitbucket.org'] = {}
config['bitbucket.org']['User'] = 'hg'
config['topsecret.server.com'] = {}
topsecret = config['topsecret.server.com']
topsecret['Host Port'] = '50022' 
topsecret['ForwardX11'] = 'no'  
config['DEFAULT']['ForwardX11'] = 'yes'

保存配置文件

保存配置文件的方式是用config对象的write方法,参数是一个file_like_object
with open('example.ini', 'w') as configfile:
   config.write(configfile)
这就完成了建立到写入config文件的过程.注意,config文件里所以的东西都是按照字符串写入的,因为ini文件就是一个文本文件.所以字典里的数字也必须是字符串形式,否则会报错.

打开已经存在的文件并进行增删改查

字典方法取值
# 读入config文件到已经建立的对象内
config.read('example.ini')
a = config.sections()  # 获得一个不包含DEFAULT section 的其他section名的字符串列表
# 可以对a的内容进行逻辑判断,看看是否存在section;还可以直接通过字典的操作方式拿数据.注意,configparser不区分大小写
print(config['DEFAULT']['Compression'])
for key in config['bitbucket.org'].values():
    print(key)

注意:在取值的时候,for 循环执行之后发现还遍历出了DEFAULT之内的内容,这是因为DEFAULT在遍历其他section的时候默认会被遍历出来;因为配置文件可能用于多用户配置,其他section内的内容可能也存在default内部相同的option,但设置可能覆盖,所以为了查看方便,会将default的内容也列出来,这样在查询的时候,知道每个独立配置哪些地方修改了默认配置,会比较方便.

用config对象方法取值:

print(config.options('bitbucket.org'))  # 取给定section内的所有设置名,连同default的一同取回,返回一个字符串列表
print(config.items('bitbucket.org'))  #取给定section里所有设置的键值对,外加default内的键值对,返回一个元组列表
print(config.get('bitbucket.org','compression')) 
# get方法有和字典相同的内容,比如.get(key,defaultvalue),这里的get方法还可以连续取值,虽然bitbucket.org的section内没有compression这一个配置,但是如果default内有,会从default内取.
# get方法给出默认值参数,如果default section内存在该键,则返回的一定是default内的值,不会返回给定的默认值.

增删改内容
可以直接用字典方法增加和修改新的section以及设置,也可以用config.add()方法来增加:

# 用.add_section方法增加section
config.add_section('new_section')
# 用set方法更新设置,set里直接按顺写写section,option,value名即可.
config.set('new_section','new','test')
# 用remove_section方法删除section,会直接连带其下的所有设置一起删除,删除失败也不会报错
config.remove_section('new_section')
# 用remove_option方法删除一个设置,需要指定section名和option名,删除失败也不会报错
config.remove_option('DEFAULT','forwardx11')
# 在删除的时候,如果不匹配,不会自动删除default的内容.

configparser模块的本质就是一个按照字典进行字处理的模块,在写自己软件的配置文件的时候,可以采用这个模块,比用字处理功能要简便很多.推荐采用config对象的方法操作,用字典的方法略显繁琐.
configparser生成的config对象的方法整理如下:

方法 说明
sections() 返回所有section名组成的列表,不包括DEFAULT
has_section(section_name) 判断section_name是否存在,注意,这其实是在sections()方法的结果里判断,所以default不会包含在内,对default的测试一定返回False
has_option(section, option) 测试一个section下的option是否存在
options(section) 返回section下的所有option名组成的字符串列表,注意,DEFAULT不含在section的可取值范围内,但是返回的结果会包含default内的option名
read(filenames, encoding=None) 读入一个config文件的内容交给对象,可以指定编码.
read_file(f, filename=None) 与read方法功能相同,参数为一个文件对象.
read_string(string) 从符合标准的一个字符串内读入数据交给对象
read_dict(dictionary) 从字典中读入,由于本身config对象就是一个嵌套的字典配置,所以从字典读入也是可以的
get(section, option, raw=False, vars=None, fallback=_UNSET) get方法与字典的get方法不同的是,基于config对象可以直接指定section和option,连续拿2层字典的值.如果当前section找不到,会从DEFAULT里取.此外可以给出默认返回值,但返回值无法覆盖default里的值
items(section=_UNSET, raw=False, vars=None) 如果section不给出,返回的是(section名,section索引)的元组列表,如果给出section名,返回的是那个section下的所有键值对构成的元组的列表.和字典的.items()类似
remove_section(section) 删除指定section和下边所有配置
remove_option(section, option) 删除指定section下的option
set(section, option, value) 直接设定指定section和option的值,相比字典的set方法可以直接穿透两层字典
write(fp, space_around_delimiters=True) 将对象写入到文件对象,如果后边参数设置为True,则option和value之间的等号两边会加上空格,为False则不加空格

hashlib模块

hash算法是一个统称,指的是散列函数.目前主要的散列函数有MD5,SHA-1,SHA-2(SHA-224、SHA-256、SHA-384,和SHA-512并称为SHA-2),SHA-3等,这里介绍了一些散列函数. 散列函数广泛的使用在各种验证和加密中,常见的如网站存放用户名和密码,其中的密码不是明文存放,而是将用户的密码经过散列函数计算后的结果(中间可能掺杂其他字符串,称作'加盐'),这样即使数据库泄露,依然可以保证大部分用户的账号安全. hashlib是个专门提供hash算法的库,里面包括md5, sha1, sha224, sha256, sha384, sha512等.

hashlib的使用方法:

选择算法然后建立一个Hash对象:
hashlib.new(name, data=b'', **kwargs)可以用来建立Hash对象,但是一般使用预定义好的名字,md5(), sha1(), sha224(), sha256(), sha384(), sha512(), blake2b(), blake2s(),
sha3_224, sha3_256, sha3_384, sha3_512, shake_128,和 shake_256.

import hashlib
a = hashlib.sha256()  # 建立一个采用sha256算法的对象

然后可以通过hash对象的各种方法来操作:

方法 说明
update(arg) 传入一个字符串作为参数,还需要指定编码,因为hash是按照字节来计算的.update会在上一次update方法调用的基础上计算hash后的值,所以反复调用update方法等于将所有传入的字符串连起来一次性进行hash计算
digest() 返回hash计算的结果,是字节类型
hexdigest() 返回hash计算的结果,是一个只包含16进制字符的unicode字符串
copy() 复制一个当前hash对象,一般用来保存hash过程中的某个状态

方法示例:

import hashlib
# 反复调用update方法的测试:
hash_obj = hashlib.md5()
hash_obj.update('conyli.cc'.encode('utf-8'))
print(hash_obj.hexdigest())
# 3a84824ae2e670370eecbb6f04412b1d

hash_obj.update(' made by minko'.encode('utf-8'))
print(hash_obj.hexdigest())
# 243b2d16688302c7495ab4288990314f

new_hash_obj = hashlib.md5()
new_hash_obj.update('conyli.cc made by minko'.encode('utf-8'))
print(new_hash_obj.hexdigest())
# 243b2d16688302c7495ab4288990314f

print(new_hash_obj.digest())
# b'$;-\x16h\x83\x02\xc7IZ\xb4(\x89\x901O'

new_hash_obj_copy = new_hash_obj.copy()
new_hash_obj_copy.update(' in year 2018.'.encode('utf-8'))
print(new_hash_obj_copy.hexdigest())
# 9f45e556f10499d238e177dcfb5e115c
LICENSED UNDER CC BY-NC-SA 4.0
Comment