`

Python 配置文件

阅读更多
  在程序中使用配置文件来灵活的配置一些参数是一件很常见的事情,配置文件的解析并不复杂,在python里更是如此,在官方发布的库中就包含有做这件事情的库,那就是ConfigParser,这里简单的做一些介绍。
    ConfigParser解析的配置文件的格式比较象ini的配置文件格式,就是文件中由多个section构成,每个section下又有多个配置项,比如:

[db]
db_host=127.0.0.1
db_port=3306
db_user=root
db_pass=password
[concurrent]
thread=10
processor=20

    假设上面的配置文件的名字为test.conf。里面包含两个section,一个是db, 另一个是concurrent, db里面还包含有4项,concurrent里面有两项。这里来做做解析:

#-*- encoding: gb2312 -*-
import ConfigParser
import string, os, sys

cf = ConfigParser.ConfigParser()
cf.read("test.conf")
# 返回所有的section
s = cf.sections()
print 'section:', s

o = cf.options("db")
print 'options:', o

v = cf.items("db")
print 'db:', v

print '-'*60
#可以按照类型读取出来
db_host = cf.get("db", "db_host")
db_port = cf.getint("db", "db_port")
db_user = cf.get("db", "db_user")
db_pass = cf.get("db", "db_pass")

# 返回的是整型的
threads = cf.getint("concurrent", "thread")
processors = cf.getint("concurrent", "processor")

print "db_host:", db_host
print "db_port:", db_port
print "db_user:", db_user
print "db_pass:", db_pass

print "thread:", threads
print "processor:", processors
#修改一个值,再写回去
cf.set("db", "db_pass", "zhaowei")
cf.write(open("test.conf", "w"))



毫无疑问, 你需要配置文件。据说配置文件能让你的系统变得可定制。
让系统变得可定制, 有三大思潮, 这决定了三种配置文件的格式:
    1. 图形界面配置工具。
       微机和 Windows 开始流行之后, 我们的用户再也不是黑客了,
       或许你的用户永远不会打开你的配置文件, 你需要给他一个图形工具, 并且帮他换尿布。
       在人类永远不会阅读配置文件的情况下, 让系统变得更简洁的方法就是使用
       机器最容易理解的格式来存储配置, 通常这是一个二进制文件。
       Pickle 是 Python 中的典型选项。
       几十年后, 有人开始以为使用机器和人都能理解 (或者都不能理解) 的格式是一个好主意, 这样就有了 XML。
       在这里, 我只想告诉大家:
           XML 确实是好东西, 但是在绝大多数情况下你其实并不真的需要他。
       而在 Zope/Plone 中, 配置被大规模地保存在 ZODB 数据库中。
       这样就产生了第一种配置文件类型, 他是人类不可读的。
    2. 常规格式的配置文件, 有著名的 httpd.conf 和 INI 等。
       基本上, INI 很弱, 而且 INI 的支持库并没有提供诸如值验证甚至设置变量默认值的功能,
       因此, 除非项目非常小你不应该使用 INI 格式。
           而在任何时候都不使用 INI 格式, 有助于你养成良好的习惯。
       httpd.conf Like 的配置文件, 是配置文件格式的巅峰之作。
       在 Python 中 ZConfig (位于 Zope2/Zope3 中) 提供了对于此种格式的支持。
       我这里有一份入门简介:
        http://eishn.blog.163.com/blog/static/65231820069310828642/
       它只是入门介绍, 你需要阅读文档、源码或者范例才能完全了解 ZConfig 的工作方式。
       尽管并不容易, 但是理解 ZConfig 会帮助你快速掌握配置文件的设计哲学。
       常规的配置文件设计和解析过于复杂, 因此你可以仅作了解。
    3. 使用 Python 本身来作为配置文件。
       Why not? 目前有许多 C 程序正在使用 Python 作为配置文件,
       而 Lighttpd 的配置文件也已经八九不离十了。
       这里是一个例子:
           # demo_conf.py
           # 配置文件
           host = '127.0.0.1'
           port = 8080
           # demo.py
           import demo_conf
           print demo_conf.host, demo_conf.port
       利用 Python 脚本作为配置文件, 在程序实现上简单, 无须格式转换, 而且功能强大。
       这个方案已经开始向传统的配置文件格式宣战。
       最后我修改了原定准备介绍 ZConfig 的计划, 今天着重来介绍这个方案。
下面, 就让我们来设计自己的配置文件格式。
要搞清楚如何设计一个配置文件, 我们首先需要搞清楚系统中有哪些数据类型是需要配置的,
并且弄清楚他们在多大程度上是可以配置的。
根据经验, 一个系统中可以定制的数据有三种:
    1. "静态" 数据, 在 C 语言中, 是用 #define 定义的。
       此类数据仅在开发期具有动态性, 一旦系统完成开发, 此类数据就是静态的。
       此类数据的变化频率最低。
       Python 程序员通常将变量名大写, 并且放在 "config.py" 中,
       通过 import config 导入使用。
    2. "默认" 配置, 这是项目配置部分最大的乱源。
       默认配置是一种用户可以在配置文件中修改的数据, 他们不是必须的, 他们有默认值。
       你很快就会发现许多 "默认" 配置实际上用户永远不会去修改他,
       在这种情况下, 这些默认配置实际上是上面所说的 "静态" 数据, 应该写入 "config.py"。
       而另一些则是常用配置, 只是带有默认值而已, 这些数据应该写入 "etc" 配置文件中。
       显而易见, 一个变量不能同时存在于 config.py 和 etc 配置文件中。
       问题在于搞清楚一个变量是属于 "静态" 数据还是 "默认" 配置是困难和不确定的。
       这最终导致你的配置文件定义朝令夕改, 而你的项目则风雨飘摇。
    3. 配置项, 毫无疑义地应该放在配置文件中。在系统投入使用后, 这是变化频率最高的数据类型。
       在配置文件中, 你又将面临另一大挑战, 就是变量类型验证。
       变量类型验证之所以讨厌, 就是因为你要同时判断一个配置变量是否存在、类型是否匹配或者是否越界,
       并且是否给以默认值。最后最糟糕的是你还需要回答一个问题:
           默认值是否需要写在配置文件中。
为了解决所有这些问题, 人们发明了 Schema。
和传统配置文件不同, 使用 Python 作为配置文件, Schema 的编写具有相当大的灵活性。
而且 Schema 能帮助你把 Python 格式的配置文件变得更加可读。
下面我就演示一下在 Python 作为配置文件格式时 Schema 的写法。
    # /PATH/TO/ETC/demo_conf.py
    # 配置文件
    import schema
    Server(
        host = '127.0.0.1',
        port = 8080
    )
    # -EOF-
    # /PATH/TO/ETC/schema.py
    #
    config = {}
    def Server(**args):
        config['host'] = args.get('host', '0.0.0.0') # 有默认值
        try:
            config['port'] = int(args.get('port', 8080)) # 带验证
        except ValueError:
            raise ValueError, '你必须是整型'
    # -EOF-
    # /PATH/TO/BIN/demo.py
    #
    import sys
    sys.path.append(r'/PATH/TO/ETC')
    import schema, demo_conf
    print schema.config['host'], schema.config['port']
    # -EOF-
好了, 接下来我们需要把 demo_conf.py 变得更像一个配置文件,
因为 "import schema" 不像是一个配置文件中应该有的东西, 我们要让 "Server" 成为预导入的变量。
最后, 我们还要把 demo_conf.py 变成 demo.conf。
这样继 PyQt4 一招鲜之后, 我们又要再次接触到自定义导入技术。
这次我们将使用类似的技术, 也是一个导入钩子 (hook), 不同的是, 这次我们不将钩子挂接到 Python 解释器。
################################################################## # -BOF-
# pyetc.py
# Python 格式的配置文件支持库
#
import sys, os.path
Module = type(sys) # 故技重演
modules = {}       # 缓存已经导入的 etc (配置) 模块
# 导入任意符合 Python 语法的文件
# 用法:
# module = pyetc.load(完整文件路径并包含扩展名, 预载入变量, 自定义返回模块类型)
#
def load(fullpath, env={}, module=Module):
    try:
        code = open(fullpath).read()
    except IOError:
        raise ImportError, 'No module named  %s' %fullpath
    filename = os.path.basename(fullpath)
    try:
        return modules[filename]
    except KeyError:
        pass
    m = module(filename)
    m.__module_class__ = module
    m.__file__ = fullpath
    m.__dict__.update(env)
    exec compile(code, filename, 'exec') in m.__dict__
    modules[filename] = m
    return m
# 移除已经导入的模块
# 用法:
# module = unload(module)
#
def unload(m):
    filename = os.path.basename(m.__file__)
    del modules[filename]
    return None
# 重新导入模块
# 用法:
# module = pyetc.reload(module)
#
def reload(m):
    fullpath = m.__file__
    try:
        code = open(fullpath).read()
    except IOError:
        raise ImportError, 'No module named  %s' %fullpath
    env = m.__dict__
    module_class = m.__module_class__
    filename = os.path.basename(fullpath)
    m = module_class(filename)
    m.__file__ = fullpath
    m.__dict__.update(env)
    m.__module_class__ = module_class
    exec compile(code, filename, 'exec') in m.__dict__
    modules[filename] = m
    return m
################################################################## # -EOF-
下面就让我们来尝试一下。
    # /PATH/TO/ETC/demo.conf
    # 配置文件
    host = '127.0.0.1'
    port = 8080
    # -EOF-
    # demo.py
    import pyetc
    conf = pyetc.load(r'/PATH/TO/ETC/demo.conf')
    print conf.host, conf.port
    # -EOF-
最后是一个较为完整的例子:
    # /PATH/TO/ETC/demo.conf
    # 服务器选项
    #
    Server(
        port = 8080 # 监听 8080 端口
    )
    # 进程控制器选项
    #
    Daemon(
        # 使用 Socket 发布进程控制器
        #     address = ('0.0.0.0', 10080),
        # 使用文件发布进程控制器
        address = var('demo.pid'),
        # 服务器进程
        program = bin('server.py'),
        # 调试开关
        verbose = True
    )
    # -EOF-
    # /PATH/TO/BIN/schema.py
    # 路径工具
    import sys, os.path
    DEMO_HOME = r'/PATH/TO/DEMO'
    ETC = lambda filename: os.path.join(DEMO_HOME, 'etc', filename)
    VAR = lambda filename: os.path.join(DEMO_HOME, 'var', filename)
    BIN = lambda filename: os.path.join(DEMO_HOME, 'bin', filename)
    #
    class Config(dict):
        # 可以像属性一样访问字典的 Key
        #     dict.key 等同于 dict[key]
        def __getattr__(self, name):
            return self[name]
    # 配置默认值
    config = Config({
        'server': Config({
            'port': 8080 # 服务器使用 8080 端口
            }),
        'daemon': Config({
            'address': VAR('daemon.pid'), # pid 文件
            'program': BIN('server.py' ), # 服务器程序
            'verbose': True
            })
    })
    # 配置接口 (不带验证)
    def Server(**args):
        config['server'].update(args)
    def Daemon(**args):
        config['daemon'].update(args)
    # 配置文件 "demo.conf" 可见的变量
    env = {'Server': Server, 'Daemon': Daemon,
        'etc': ETC, 'var': VAR, 'bin': BIN}
    # -EOF-
    # /PATH/TO/BIN/demo.py
    # 这里启动一个 Daemon 管理器,
    # 注意: 这里的 daemon.py 是一个假想库, 无须理会
    import pyetc
    from daemon import Daemon
    def start():
        # 读取配置文件
        # demo.conf
        pyetc.load(schema.ETC('demo.conf'), env=schema.env)
        conf = schema.config.daemon
        # 创建 Daemon 对象
        daemon = Daemon(
            address = conf.address, # 进程控制器地址/pid 文件位置
            program = conf.program, # 后台进程程序位置
            verbose = conf.verbose  # 调试
            )
        print '进程管理器已经启动'
        daemon()
    if __name__ == '__main__':
        start()
    # -EOF-
分享到:
评论

相关推荐

    editplus_python配置文件方法

    以下是关于"editplus_python配置文件方法"的详细说明: 1. **配置Python语法高亮**:EditPlus可以通过设置文件实现对Python源代码的语法高亮显示。Python.acp文件就是用于定义Python语言的语法高亮规则。打开这个...

    Python的配置文件

    在Python编程中,配置文件(通常为ini、cfg或json格式)是用于存储应用程序特定设置的重要工具。这些文件允许开发者将程序的配置信息与代码分离,使得用户可以根据自己的需求定制应用,同时也方便了代码的管理和维护...

    python3.6的配置文件写入时保留注释

    python3.6,对其配置文件的读写进行了修改,目的是在设置值(会导致写文件)时,对原始文件中的注释进行保留。由于是对原工具中代码的修改,所以建议在使用此文件进行覆盖之前,先对原文件进行备份,防止在一些极端...

    vimrc linux Python配置文件

    Linux下,VIM,Python自动缩进配置文件,放到个人目录下即可,攺名为.vimrc

    vscode运行C++和python配置文件

    VSCode(Visual Studio Code)是一款由微软开发的免费、开源...记住,每次更改配置文件后,VSCode可能需要重启才能应用新的设置。不断调整这些配置,以适应个人的工作习惯和项目需求,将使你的编程体验更加高效和愉快。

    Python配置文件处理的方法教程

    配置文件一般区别于Python代码,会单独存放在一个文件夹中,方便管理,常见的配置文件格式有.conf, .ini, .yaml等。 本文使用Python中的configparser模块来处理conf、ini配置文件。 首先需要安装configparser模块...

    Python-loadcfpython配置文件加载器

    "loadcf-python配置文件加载器"是一个专门用于处理这种任务的库,它简化了从各种格式(如JSON、YAML、INI等)加载配置的过程。这个库的目标是提供一个简单易用、功能丰富的接口,让开发者能够轻松地集成配置管理到...

    python配置文件写入过程详解

    Python配置文件写入详解的知识点涵盖了Python标准库中的ConfigParser模块的使用方法,以及在使用该模块进行配置文件读写操作时需要注意的细节。配置文件是存储程序配置参数的一种文件格式,常见的扩展名有.conf、....

    Python实现读取Properties配置文件的方法

    在Python编程中,有时我们需要处理Java开发中常用的`.properties`配置文件。虽然Python标准库并未直接提供处理此类文件的模块,但我们可以自定义一个类来实现这个功能。本篇文章将详细探讨如何通过Python来读取并...

    python读取配置文件

    在Python编程中,读取配置文件是一个常见的任务,它允许我们分离程序的配置信息,如数据库连接、API密钥或应用程序设置,以便于管理和维护。本文将深入探讨如何使用Python来读取配置文件,主要关注从`.ini`、`.json`...

    python定期备份交换机配置文件二

    Python 定期备份交换机配置文件 Python script 介绍 在网络维护中,交换机配置文件的备份是非常重要的。为了避免配置文件的丢失,需要定期备份交换机配置文件。本文将介绍如何使用 Python Script 实现交换机配置...

    python读取ini配置文件过程示范

    在当今的软件开发实践中,配置文件是分离程序运行环境和程序代码的重要方式,尤其在使用Python语言开发应用程序时。一个常见的配置文件格式是INI文件,它以简单的键值对结构存储配置信息。Python标准库中的...

    tuna:Python配置文件查看器

    金枪鱼是受启发的现代轻量级Python配置文件查看器。 它处理运行时和导入配置文件,具有最小的依赖性,使用和 ,并且避免了SnakeViz中存在的(请参见下文),并且速度也更快。 使用以下命令创建运行时配置文件 ...

    配置描述文件python脚本

    1. **Python配置文件格式** Python支持多种配置文件格式,如`.ini`、`.cfg`、JSON、YAML等。其中,`configparser`模块是Python标准库的一部分,专门用于处理`.ini`格式的配置文件。这个模块允许我们读取、写入和...

    Python配置文件解析模块ConfigParser使用实例

    主要介绍了Python配置文件解析模块ConfigParser使用实例,本文讲解了figParser简介、ConfigParser 初始工作、ConfigParser 常用方法、ConfigParser使用实例等内容,需要的朋友可以参考下

    Python常见配置问题详细教程

    Python 配置文件详细教程 Python 中的配置文件是一种常用的存储固定参数或常量的方法,在开发过程中,我们常常会用到一些固定参数或者是常量。对于这些较为固定且常用到的部分,往往会将其写到一个固定文件中,避免...

    如何写python的配置文件

    本文将详细介绍如何创建、读取和动态写入Python配置文件。 一、创建配置文件 创建Python配置文件的第一步是在硬盘上创建一个`.ini`文件。例如,可以在D盘创建一个名为`test.ini`的文件,内容如下: ```ini ...

    python3.6的配置文件写入时保留注释(更正一个bug)

    python3.6,对其配置文件的读写进行了修改,目的是在设置值(会导致写文件)时,对原始文件中的注释进行保留。由于是对原工具中代码的修改,所以建议在使用此文件进行覆盖之前,先对原文件进行备份,防止在一些极端...

Global site tag (gtag.js) - Google Analytics