improve your python code(11)

来源:互联网 发布:数控机床的编程方法 编辑:程序博客网 时间:2024/05/19 02:00

  • ini配置文件
  • 深入掌握ConfigParser

1. ini配置文件

如果我们程序没有任何配置文件时,这样的程序对外是全封闭的,一旦程序需要修改一些参数必须要修改程序代码本身并重新编译,这样很不好,所以要用配置文件,让程序出厂后还能根据需要进行必要的配置;配置文件有很多如INI配置文件,XML配置文件,还有就是可以使用系统注册表等。在早期的windows桌面系统中主要是用INI文件作为系统的配置文件,从win95以后开始转向使用注册表,但是还有很多系统配置是使用INI文件的。其实INI文件就是简单的text文件,只不过这种txt文件要遵循一定的INI文件格式。“.INI ”就是英文 “initialization”的头三个字母的缩写;当然INI file的后缀名也不一定是”.ini”也可以是”.cfg”,”.conf ”或者是”.txt”。

经典格式:

INI文件的格式很简单,最基本的三个要素是:parameters,sections和comments。

什么是parameters?

INI所包含的最基本的“元素”就是parameter;每一个parameter都有一个name和一个value,name和value是由等号“=”隔开。name在等号的左边。

如:

name = value

什么是sections ?

所有的parameters都是以sections为单位结合在一起的。所有的section名称都是独占一行,并且sections名字都被方括号包围着([ and ])。在section声明后的所有parameters都是属于该section。对于一个section没有明显的结束标志符,一个section的开始就是上一个section的结束,或者是end of the file。Sections一般情况下不能被nested,当然特殊情况下也可以实现sections的嵌套。

section如下所示:

[section]

什么是comments ?

在INI文件中注释语句是以分号“;”开始的。所有的所有的注释语句不管多长都是独占一行直到结束的。在分号和行结束符之间的所有内容都是被忽略的。

注释实例如下:

;comments text

INI实例:

;db_config.conf[baseconf]host=localhostuser=rootpassword=rootdb=your_db_nameuse_unicode=Truecharset=utf8[concurrent]processor=20

2. 深入掌握ConfigParser

configparser 模块能被用来读取配置文件。例如,假设你有如下的配置文件:

; config.ini; Sample configuration file[installation]library=%(prefix)s/libinclude=%(prefix)s/includebin=%(prefix)s/binprefix=/usr/local# Setting related to debug configuration[debug]log_errors=trueshow_warnings=False[server]port: 8080nworkers: 32pid-file=/tmp/spam.pidroot=/www/rootsignature:=================================Brought to you by the Python Cookbook=================================

下面是一个读取和提取其中值的例子:

> > > from configparser import ConfigParser> > > cfg = ConfigParser()> > > cfg.read('config.ini')> > > ['config.ini']> > > cfg.sections()> > > ['installation', 'debug', 'server']> > > cfg.get('installation','library')> > > '/usr/local/lib'> > > cfg.getboolean('debug','log_errors')True> > > cfg.getint('server','port')> > > 8080> > > cfg.getint('server','nworkers')> > > 32> > > print(cfg.get('server','signature'))\=================================Brought to you by the Python Cookbook\=================================

如果有需要,你还能修改配置并使用 cfg.write() 方法将其写回到文件中。例如:

cfg.set('server','port','9000')cfg.set('debug','log_errors','False')import syscfg.write(sys.stdout)[installation]library = %(prefix)s/libinclude = %(prefix)s/includebin = %(prefix)s/binprefix = /usr/local
[debug]log_errors = Falseshow_warnings = False[server]port = 9000nworkers = 32pid-file = /tmp/spam.pidroot = /www/rootsignature =      =================================      Brought to you by the Python Cookbook      =================================

讨论
配置文件作为一种可读性很好的格式,非常适用于存储程序中的配置数据。 在每个配置文件中,配置数据会被分组(比如例子中的“installation”、 “debug” 和 “server”)。 每个分组在其中指定对应的各个变量值。

对于可实现同样功能的配置文件和Python源文件是有很大的不同的。 首先,配置文件的语法要更自由些,下面的赋值语句是等效的:

prefix=/usr/local
prefix: /usr/local
配置文件中的名字是不区分大小写的。例如:

cfg.get('installation','PREFIX')
'/usr/local'
cfg.get('installation','prefix')
'/usr/local'

在解析值的时候,getboolean() 方法查找任何可行的值。例如下面都是等价的:

log_errors = true
log_errors = TRUE
log_errors = Yes
log_errors = 1
或许配置文件和Python代码最大的不同在于,它并不是从上而下的顺序执行。 文件是安装一个整体被读取的。如果碰到了变量替换,它实际上已经被替换完成了。 例如,在下面这个配置中,prefix 变量在使用它的变量之前或之后定义都是可以的:

[installation]
library=%(prefix)s/lib
include=%(prefix)s/include
bin=%(prefix)s/bin
prefix=/usr/local
ConfigParser 有个容易被忽视的特性是它能一次读取多个配置文件然后合并成一个配置。 例如,假设一个用户像下面这样构造了他们的配置文件:

; ~/.config.ini
[installation]
prefix=/Users/beazley/test

[debug]
log_errors=False
读取这个文件,它就能跟之前的配置合并起来。如:

> > > # Previously read configuration> > >> > > cfg.get('installation', 'prefix')> > > '/usr/local'> > > # Merge in user-specific configuration> > >> > > import os> > > cfg.read(os.path.expanduser('~/.config.ini'))> > > ['/Users/beazley/.config.ini']> > > cfg.get('installation', 'prefix')> > > '/Users/beazley/test'> > > cfg.get('installation', 'library')> > > '/Users/beazley/test/lib'> > > cfg.getboolean('debug', 'log_errors')> > > False

仔细观察下 prefix 变量是怎样覆盖其他相关变量的,比如 library 的设定值。 产生这种结果的原因是变量的改写采取的是后发制人策略,以最后一个为准。 你可以像下面这样做试验:

> > > cfg.get('installation','library')> > > '/Users/beazley/test/lib'> > > cfg.set('installation','prefix','/tmp/dir')> > > cfg.get('installation','library')> > > '/tmp/dir/lib'
0 0