前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >python 配置文件读写

python 配置文件读写

作者头像
orientlu
发布于 2018-09-13 03:01:09
发布于 2018-09-13 03:01:09
1.9K00
代码可运行
举报
文章被收录于专栏:orientluorientlu
运行总次数:0
代码可运行

@(python)

[TOC]

前言

将代码中的配置项抽取到配置文件中,修改配置时不需要涉及到代码修改,避免面对一堆令人抓狂的 magic number,极大的方便后期软件的维护。

python 本身提供标准的配置读写模块 configParse(python2,python3 修改为configparser),用于读取 ini 格式的配置文件。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
[DEFAULT]
ServerAliveInterval = 45
Compression = yes

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

除了标准库提供的模块,通过第三方模块 pyYAML, 可以读写 yaml[1]式的配置文件。

本文介绍 python 通过 configParser 和 pyYAML 读写配置文件的方法。

configParser

Note The ConfigParser module has been renamed to configparser in Python 3. The 2to3 tool will automatically adapt imports when converting your sources to Python 3.

python2 和 python3 中此模块有些许不同,旧代码可以通过工具进行转换。 目前来说,python2 在项目中仍有使用,所以以下对在 python2 和 python3 下模块的使用都进行介绍。

python2 - ConfigParser

在ConfigParser 中提供了三个类:

  • RawConfigParser
  • ConfigParser
  • SafeConfigParser 三个以此在前者的基础进行扩展,接口提供额外可选参数,提供更加复杂的功能,主要差别应该体现在对 %(value_name)s进行参数替换(value_name 为同section或者[DEFAULT]中的其他变量名才行)

这里使用的默认配置文件 default.cfg 内容如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
[DEFAULT]
default_name = lcd

[Section1]
an_int = 15
a_bool = true
a_float = 3.1415
baz = fun
bar = Python
foo = %(bar)s is %(baz)s!
name = s1_%(default_name)s   ; DEFAULT section's value
基本读写

使用 RawConfigParser 实现配置文件的基本的读写操作。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import ConfigParser

test_cfg = "./default.cfg"
config_raw = ConfigParser.RawConfigParser()
config_raw.read(test_cfg)

# 读取配置文件中 [DEFAULT]
defaults = config_raw.defaults()
print defaults

# 读取指定section下的value值
a_float = config_raw.getfloat('Section1', 'a_float')
print "-- number : %f type is : %s"%(a_float ,type(a_float))

# 设置指定section下的value值
# 此时没有写入文件,保存在内存实例中
a_float = 2.14159
config_raw.set('Section1', 'a_float', a_float)
a_float = config_raw.getfloat('Section1', 'a_float')
print "-- number : %f type is : %s"%(a_float ,type(a_float))

# 读取带有参数替换模板的变量,但是没有替换参数
print "-- RawConfigParser just get raw value"
str_foo = config_raw.get('Section1', 'foo')
print str_foo

对应不同数据类型,除了调用get()获取配置文件中的原始内容,还可以使用对应的接口,getint, getboolean, 其中,布尔值 True 对应的是 1、yes、true 和 on, False 对应 0、no、false 和 off。

运行结果

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
OrderedDict([('default_name', 'lcd')])
-- number : 3.141500 type is : <type 'float'>
-- number : 2.141590 type is : <type 'float'>
-- RawConfigParser just get raw value
%(bar)s is %(baz)s!
参数替换

相比 RawConfigParser, 对于配置文件中foo = %(bar)s is %(baz)s! 这种格式的变量,在读取的时候如果想要取得替换后的值,需要使用类 ConfigParser 或者 SafeConfigParser 。 代码如下

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
config = ConfigParser.ConfigParser()
config.read(test_cfg)

print "-- ConfigParser can get interpolation"
## get 接口添加参数 raw,raw=1 时直接返回配置文件中的值,不做参数替换
## raw 默认为0,设置为0时,返回替换后的值
str_foo = config.get('Section1', 'foo', raw=1)
#等同 str_foo = config.get('Section1', 'foo', 1)
print str_foo
str_foo = config.get('Section1', 'foo')
print str_foo
str_foo = config.get('Section1', 'foo', 0)
print str_foo

print "-- After set a new value"
str_foo = "%(name)s is %(baz)s!"
config.set('Section1', 'foo', str_foo)
str_foo = config.get('Section1', 'foo', 1)
print str_foo
str_foo = config.get('Section1', 'foo')
print str_foo

## raw=0,返回替换后的值,替换的变量是在同 section 下或者 default section 中查找
str_foo = config.get('Section1', 'name')
print str_foo

## 接口还有另外一个可选参数 vars,
## 设置后,查询配置 values 时,会优先从vars这个{}寻找匹配的key返回
## 没有再去寻找配置文件中的。
print "-- use default value if pass by vars={}"
a_float = config.get('Section1', 'a_float1', vars={'a_float1':'0.01'})
print "-- number : %f type is : %s"%(float(a_float) ,type(a_float))

运行结果

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
-- ConfigParser can get interpolation
%(bar)s is %(baz)s!
Python is fun!
Python is fun!
-- After set a new value
%(name)s is %(baz)s!
s1_lcd is fun!
s1_lcd
-- use default value if pass by vars={}
-- number : 0.010000 type is : <type 'str'>
使用默认参数

有些配置参数有时候配置文件中并没有设置,此时程序中应该有对应的默认值,当找配置文件中查找不到时,使用配置值。注意和上一小节设置 vars={}不同,此处是优先返回配置文件的值,没有才返回设置的默认值,上面则相反。

如下

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
## 设置默认值 name : default_name
config = ConfigParser.ConfigParser({'name' : 'default_name'})
config.readfp(open('./default.cfg'))
    
# 读取存在的配置值,返回的是配置文件中的值
str_foo = config.get('Section1', 'name')
print str_foo
print "-- use default value"
config.remove_option('Section1', 'name')
# 读取不存在的配置值,返回设置的默认值
str_foo = config.get('Section1', 'name')
print str_foo

运行结果

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
s1_lcd
-- use default value
default_name
使用默认配置文件

程序配置时,可以设置多个配置文件,并按照一定的优先级使用相应的配置文件,比如系统默认有个配置文件,不同的用户下又使用不同的配置文件,程序运行时优先使用用户配置文件中的配置参数,如果用户配置文件不存在或者对应参数没有设置,再读取系统默认配置文件中的参数值。 此处,默认配置文件是开头提供的 default.cfg

另新加两个配置文件:

user1.cfg

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
[DEFAULT]
default_name = user1

[Section1]
name = s1_%(default_name)s   ; DEFAULT section's value

user2.cfg

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
[DEFAULT]
default_name = user1

[Section1]
name = s1_%(default_name)s   ; DEFAULT section's value

我们希望,参数使用优先级按照 user3.cfg > uer2.cfg > user1.cfg > default.cfg 使用 实现方式如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
config = ConfigParser.ConfigParser()
## 设置默认的配置文件
## 注意此文件不存在会raise异常
config.readfp(open('./default.cfg'))
## 设置可选配置文件,最后优先级最高,文件不存在则忽略
config.read(['./user1.cfg', './user2.cfg', './user3.cfg'])
# readfp 必须先调用后才能调用read,否则read中都打不开,会报错
# config.read(['./user11111111.cfg', './user22222222.cfg'])

## 可选文件中找不到的参数,在default中查找
an_int = config.getint('Section1', 'an_int')
print "-- number : %f type is : %s"%(an_int ,type(an_int))

## 使用可选文件中存在的参数
str_foo = config.get('Section1', 'name')
print str_foo

运行结果

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
-- number : 15.000000 type is : <type 'int'>
s1_user2

默认文件需要存在,运行时加载失败会报错,其他可选设置文件如果找不到,直接忽略。

python3 - configparser

可能考虑兼容性,前面 python2 中实现的三个类在 python3 中依然支持。对于 python2 提供的参考上一节内容,接下面我们看看 python3 的使用。

基本读写

同 python2 差不多,加载配置文件后可以通过诸如 get, getint的接口读取参数值,也可以像读取 dict 一样读取配置参数。

读取的配置文件example.ini 如下

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
[DEFAULT]
serveraliveinterval = 45
compression = yes
compressionlevel = 9
forwardx11 = yes

[bitbucket.org]
user = hg 
;comment
#comment 

[topsecret.server.com]
port = 50022
forwardx11 = no

使用接口读取上述配置文件内容

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import configparser

config = configparser.ConfigParser()
print("- Empty config %s"%config.sections())

print("- Load config file")
config.read("./example.ini")
## 此处返回的sections list不包括 default
print("> config sections : %s"%config.sections()) 
print('bitbucket.org' in config )  ## 判断配置文件中是否存在该 section
print("> Load config file is :")

for section in config.keys():
    print("[{s}]".format(s=section))
    for key in config[section]:
        print("{k} = {v}".format(k=key, v=config[section][key]))

## 如访问 dict 一样读取配置内容
print("\n- Get value like dict :user =  %s"%config['bitbucket.org']['user'])
conf_bitbucket = config['bitbucket.org']
print(conf_bitbucket['user'])

"""
The DEFAULT section which provides default values for all other sections"""
print("\n- DEFAULT Section")
## default 是所有section的默认设置,备胎...
for key in config['bitbucket.org']: print(key)
print("> Get default value : forwardx11 = %s\n"%config['bitbucket.org']['forwardx11'])

## 读取不同数据类型的配置参数
print("\n- Support datatypes")
forwardx11 = config['bitbucket.org'].getboolean('forwardx11')
int_port = config.getint('topsecret.server.com', 'port')
float_port = config.getfloat('topsecret.server.com', 'port')
print("> Get int port = %d type : %s"%(int_port, type(int_port)))
print("> Get float port = %f type : %s"%(float_port, type(float_port)))

运行结果如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
- Empty config []
- Load config file
> config sections : ['bitbucket.org', 'topsecret.server.com']
True
> Load config file is :
[DEFAULT]
serveraliveinterval = 45
compression = yes
compressionlevel = 9
forwardx11 = yes
[bitbucket.org]
user = hg
serveraliveinterval = 45
compression = yes
compressionlevel = 9
forwardx11 = yes
[topsecret.server.com]
port = 50022
forwardx11 = no
serveraliveinterval = 45
compression = yes
compressionlevel = 9

- Get value like dict :user =  hg
hg

- DEFAULT Section
user
serveraliveinterval
compression
compressionlevel
forwardx11
> Get default value : forwardx11 = yes


- Support datatypes
> Get int port = 50022 type : <class 'int'>
> Get float port = 50022.000000 type : <class 'float'>
默认返回

在读取配置参数时,设置如果在配置文件中查找不到指定值,则默认返回的值。 在指定 section 和 default 中都找不到查找的值,就会直接返回设置的 fallback, 而不是 raise 错误。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
print("\n- Return Fallback")
print("> Get value user = %s"%(config.get('bitbucket.org', 'user')))
print("> Get value user = %s"%(config.get('bitbucket.org', 'user', fallback="fallback_name")))
print("> Get value forwardx11 = %s"%(config.getboolean('bitbucket.org', 'forwardx11', fallback=False)))
print("> Get value forwardx22 = %s"%(config.getboolean('bitbucket.org', 'forwardx22', fallback=False)))
print("> Get value user2 = %s"%(config.get('bitbucket.org', 'user2', fallback="fallback_name")))

运行结果如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
- Return Fallback
> Get value user = hg
> Get value user = hg
> Get value forwardx11 = True
> Get value forwardx22 = False
> Get value user2 = fallback_name
参数替换

在 python2 中提到的参数替换,pyton3 中默认使用的 BasicInterpolation(), 直接支持,在上面就提到,这种替换,变量必须是同个 section(包括default),如果要使用到其他 section 的参数,就需要使用 ExtendedInterpolation(),并且,语法上会有些许不同。

如下,basic_interpolation.ini 是基础的替换配置文件,和 python2 一样

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
[Paths]
home_dir: /Users
my_dir: %(home_dir)s/lumberjack
my_pictures: %(my_dir)s/Pictures

而以下这个,扩展到参数可以使用不同的 section, 在 extended_interpolation.ini 中,替换的参数写法是 ${section_name: value_name}

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
[Common]
home_dir: /Users
library_dir: /Library
system_dir: /System
macports_dir: /opt/local

[Frameworks]
Python: 3.2
path: ${Common:system_dir}/Library/Frameworks/

[Arthur]
nickname: Two Sheds
last_name: Jackson
my_dir: ${Common:home_dir}/twosheds
my_pictures: ${my_dir}/Pictures
python_dir: ${Frameworks:path}/Python/Versions/${Frameworks:Python}

对以上两个配置文件进行读取,如下代码

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
print("\n- BasicInterpolation")
#default : config = configparser.ConfigParser(interpolation=configparser.BasicInterpolation())
## 默认使用的 interpolation 就是 BasicInterpolation()
config.read("./basic_interpolation.ini")
print("> Get raw value %s"%(config.get('Paths', 'my_dir', raw = 1)))
print("> Get value %s"%(config.get('Paths', 'my_dir', raw = 0)))


print("\n- ExtendedInterpolation - other sections")
config = configparser.ConfigParser(interpolation=configparser.ExtendedInterpolation())
config.read("./extended_interpolation.ini")
print("> Get raw value %s"%(config.get('Arthur', 'python_dir', raw = 1)))
print("> Get value %s"%(config.get('Arthur', 'python_dir', raw = 0)))

运行结果 :

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
- BasicInterpolation
> Get raw value %(home_dir)s/lumberjack
> Get value /Users/lumberjack

- ExtendedInterpolation - other sections
> Get raw value ${Frameworks:path}/Python/Versions/${Frameworks:Python}
> Get value /System/Library/Frameworks//Python/Versions/3.2

pyYAML

jason

参考


  1. http://www.ruanyifeng.com/blog/2016/07/yaml.html?f=tt
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2018.05.08 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
【最佳实践】巡检项:内容分发网络(CDN)域名绑定证书到期
如果https证书过期,访问https链接将会报证书无效的错误, 影响https协议的链接访问。 为了确保https功能正常使用,我们建议定期检查https证书有效期,提前发现即将过期的证书进行更新处理。
cathyzhu
2022/03/28
3K0
【最佳实践】巡检项:内容分发网络(CDN)预热容量
域名接入CDN后,初始状态下,加速节点上无任何域名资源缓存,当用户请求至 CDN 加速节点时,需要回源拉取资源同时根据策略进行缓存。腾讯云 CDN 提供资源预热功能,无需用户请求触发,通过在 CDN 控制台提交资源列表,将指定资源加载至加速节点。
cathyzhu
2022/04/25
1.2K0
【最佳实践】巡检项:内容分发网络(CDN)URL刷新容量
当站点上存在违规资源(如涉黄、涉毒、涉赌)被发现时,删除源站资源后,由于节点缓存资源仍可被访问到,为维护网络环境,可通过 URL 刷新删除缓存资源,保证及时清理。 另外当源站资源发生变更, 为避免全网用户受节点缓存影响仍访问到旧的资源上,也可以通过URL刷新删除缓存资源。
cathyzhu
2022/04/24
2.5K0
【最佳实践】巡检项:内容分发网络(CDN)IP 访问限频
对于有些业务,用户希望对业务资源的访问来源进行控制,防止恶意的用户盗刷场景。对于这种场景,我们推荐设置『IP访问限频配置』通过对单IP节点在每一秒钟的访问次数进行合理的阀值限制, 从而减少这种问题的发生。
cathyzhu
2022/03/31
1.6K0
【最佳实践】巡检项:内容分发网络(CDN)用量封顶配置
腾讯云 CDN 当前为按量后付费,如果没有安全防护措施,可能由于恶意盗刷产生大量带宽或者流量,导致产生高额账单。为了尽量避免此类潜在风险,我们建议用户通过一系列的防护机制对域名进行保护。
cathyzhu
2022/04/02
1.1K0
小程序开发为什么要https和SSL证书呢?在哪里可以申请办理?
小程序开发为什么要https和SSL证书呢?在哪里可以申请办理?合信ssl证书可以一手办您申请办理好!
合信ssl证书
2019/07/11
1.5K0
【最佳实践】巡检项:内容分发网络(CDN)目录刷新容量
在源站点将新资源覆盖至同名旧资源后,为避免全网用户受节点缓存影响仍访问到旧的资源上,可通过提交对应资源的 URL/目录进行刷新,清空全网缓存后,全网用户可直接访问到最新资源。如果想批量处理某个目录下的所有的资源时,这时候可用目录刷新的方式。如果刷新配额不够,可以酌情分目录刷新或提升目录刷新配额。
cathyzhu
2022/04/24
2.2K0
如何快速实现内容分发网络切换到腾讯云CDN
内容分发网络(Content Delivery Network,CDN)通过将站点内容发布至遍布全球的海量加速节点,使其用户可就近获取所需内容,避免网络拥堵、地域、运营商等因素带来的访问延迟问题,有效提升下载速度、降低响应时间,提供流畅的用户体验。
Charlie Huston
2020/05/14
7.1K0
如何快速实现内容分发网络切换到腾讯云CDN
网站申请https证书有必要吗?http升级为https的好处
  我们在浏览各大网站的时候,会发现有些网站网址是以http://开头,有些是以https://开头的,这是什么原因呢?以https://开头的网站就是安装了https证书(也就是SSL证书)的缘故。随着互联网的发展,带来便利的同时也带了一定的危险,比如:信息泄露等。网站安装SSL证书将http升级为https尤为重要。
安信SSL证书
2019/07/25
2.1K0
网站申请https证书有必要吗?http升级为https的好处
【最佳实践】巡检项:内容分发网络(CDN)开启URL鉴权
一般情况下,在 CDN 上分发的内容默认为公开资源,用户拿到 URL 后均可进行访问,如果不进行任何形式的鉴权,就可能会被非法站点恶意盗刷盗用,产生损失。我们特别推荐相关盗刷敏感的业务一定开启url鉴权,防止非法网站盗用。
cathyzhu
2022/04/22
1.6K0
玩转腾讯云CDN
加速区域选择为中国境内或全球时,需要先完成 ICP 备案,若您的域名尚未完成 ICP 备案,您可以使用腾讯云网站备案。
杜志强
2021/07/25
11.6K0
玩转腾讯云CDN
【最佳实践】巡检项:内容分发网络(CDN)未配置缓存规则
缓存是CDN提供的最重要的一个功能, 终端用户仅需要访问最近的CDN节点即可获取静态内容, 并缓解源站的压力, 提升终端用户的访问体验。 所以我们建议接入CDN的域名,都需要根据业务的实际情况,设置缓存策略; 如果不设置任何缓存策略,会降低命中率,增大回源压力, 减少使用CDN的收益。
cathyzhu
2022/04/28
9040
HTTP后台服务拥抱HTTPS方案
自学微信小程序时,看到小程序现在只支持https了。而且现在chrome中浏览http的网站,网址前都会直接显示“不安全”字样。http是明文传输,相当于所有信息在网络上裸奔,没有安全性可言。现在都2018年了,大家在做新项目的时候还是都上https吧。
J_J
2018/10/03
5.1K0
HTTP后台服务拥抱HTTPS方案
【最佳实践】巡检项:内容分发网络(CDN)COS源跨域一致性
在CDN源站是COS的场景下,如果COS服务配置了跨域策略, CDN没有配置相关的跨域策略, 那么当用户请求CDN时, 如果节点没有缓存,则发起回源。 节点会缓存源站返回的跨域头部。 后续请求再次命中接点时,会直接返回缓存的跨域头, 这样可能会出现返回跨域头信息不匹配,造成的跨域错误。
cathyzhu
2022/04/27
9910
HSTS详解|洞见
缘起:启用HTTPS也不够安全 有不少网站只通过HTTPS对外提供服务,但用户在访问某个网站的时候,在浏览器里却往往直接输入网站域名(例如www.example.com),而不是完整的URL(例如ht
ThoughtWorks
2018/04/13
1.3K0
HSTS详解|洞见
【最佳实践】巡检项:云直播(CSS)SSL证书有效期
如果您的直播播放采用的是https协议,则需要关注SSL证书的有效期。若SSL证书过期,则 https 访问会出现无法访问的情况。
tillyyang 杨枫
2022/04/20
5220
cdn被劫持怎么办?如何避免cdn劫持?
Cdn能够加速用户的网站访问速度,虽然很多人对于其中的原理并不是十分清楚,但这并不妨碍用户对其的使用。其实CDN技术本身就是对用户dns劫持,只是这种劫持是良性的友好的是为用户提供帮助的,那么cdn被劫持怎么办?如何避免cdn劫持?
用户8715145
2021/09/18
3.9K0
cdn被劫持怎么办?如何避免cdn劫持?
【最佳实践】巡检项:内容分发网络(CDN)错误状态码占比
一般来讲,若请求返回的状态码是4xx、5xx,会被视为错误状态码。如果这些异常状态码的请求比例超过5%,则需要引起重视及深入分析,看看是什么原因导致,对实际业务影响几何。
陈志杰
2022/04/12
9870
【最佳实践】巡检项:内容分发网络(CDN)单链接下行限速
对于有些下载业务,比如游戏版本发布更新等场景,可能会在产生较大的CDN的峰值带宽。如果是带宽计费,可能会对成本有所影响。 在不影响业务的情况下,建议可以适当情况下对下行速度进行限制。
cathyzhu
2022/04/02
6100
ASP.NET Core 6框架揭秘实例演示[36]:HTTPS重定向
HTTPS是确保传输安全最主要的手段,并且已经成为了互联网默认的传输协议。不知道读者朋友们是否注意到当我们利用浏览器(比如Chrome)浏览某个公共站点的时候,如果我们输入的是一个HTTP地址,在大部分情况下浏览器会自动重定向到对应HTTPS地址。这一特性源于浏览器和服务端针对HSTS(HTTP Strict Transport Security)这一HTTP规范的支持。ASP.NET利用HstsMiddleware和HttpsRedirectionMiddleware这两个中间件提供了对HSTS的实现。(本文提供的示例演示已经同步到《ASP.NET Core 6框架揭秘-实例演示版》)
蒋金楠
2023/06/09
8380
ASP.NET Core 6框架揭秘实例演示[36]:HTTPS重定向
推荐阅读
相关推荐
【最佳实践】巡检项:内容分发网络(CDN)域名绑定证书到期
更多 >
LV.0
这个人很懒,什么都没有留下~
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档