大部分程序的配置文件比如经常见到的.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_objectwith 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