Python中使用设置文件的最佳实践是什么?

475

我有一个命令行脚本,需要运行很多参数。现在我已经到了参数过多的地步,希望一些参数以字典形式呈现。

为了简化操作,我想用设置文件来运行脚本。但我不知道应该使用哪个库来解析这个文件。做这件事情的最佳实践是什么?当然我可以自己动手写代码,但如果有相关的库,我也愿意借鉴。

一些要求:

  • 不想使用 pickle ,而是直接用文本文件来读取和编辑。
  • 希望能够在文件中添加类似于字典的数据,即支持某种形式的嵌套。

以下是一个简化的伪例子文件:

truck:
    color: blue
    brand: ford
city: new york
cabriolet:
    color: black
    engine:
        cylinders: 8
        placement: mid
    doors: 2

8
这个示例文件的语法实际上是YAML格式,请查看Benson的答案。 - Skippy le Grand Gourou
1
我建议使用 python-box,请参考这个答案 - evolved
我建议尝试使用trapdoor进行即插即用配置(免责声明:我是trapdoor的作者)。 - clmcleod
3
从Python 3.11开始,tomlllib包成为标准库的一部分,并且是解析美妙的TOML格式配置的首选方式。(对于早期版本的Python,可以使用相应的tomli包进行pip安装。)TOML依赖于正式规范(不像INI),易于阅读并允许注释(不像JSON),并限制了复杂性(不像YAML)。 - sammy
4个回答

282

你可以创建一个普通的Python模块,比如config.py,像这样:

truck = dict(
    color = 'blue',
    brand = 'ford',
)
city = 'new york'
cabriolet = dict(
    color = 'black',
    engine = dict(
        cylinders = 8,
        placement = 'mid',
    ),
    doors = 2,
)

并像这样使用它:

import config
print(config.truck['color'])  

102
如果您想让低权限用户仅能更改配置文件,这么做是一个相当糟糕的主意,因为这样您实际上允许他们悄悄地插入特权代码。 - nikolay
213
允许“低权限”用户更改更高权限程序的配置可能本身就是一个值得怀疑的设置。 - XTL
26
您可能在使用像py2app这样的工具打包项目以进行部署时遇到问题。一旦分发应用程序,用户可能无法编辑配置文件,因为这会使应用程序的签名无效。 - bschwagg
35
这种(本来非常方便的)选项的主要缺点是.py文件是可执行的,因此在尝试通过“import”加载配置时可能会运行任何类型的代码。从安全角度来看,这是不可接受的。 - Apalala
7
可以使用ast.literal_eval安全地执行这个操作吗?https://docs.python.org/3/library/ast.html#ast.literal_eval - André C. Andersen
显示剩余10条评论

265

你提供的示例配置实际上是有效的YAML。事实上,YAML 满足你所有的要求,被许多编程语言实现,并且极易阅读。我强烈建议你使用它。PyYAML 项目提供了一个很好的 Python 模块来实现 YAML。

使用 yaml 模块非常简单:

import yaml
config = yaml.safe_load(open("path/to/config.yml"))

7
YAML 是我经常使用的东西;其格式可以非常简单,也可以支持嵌入 Python 代码,而且标准库会自动处理解析和清洗,让你事半功倍。 - Todor Minakov
25
同意。对于您或编写YAML的用户,这是我所知道的最好的YAML参考资料:http://camel.readthedocs.org/en/latest/yamlref.html 。官方文档很不幸,只是面向实现者的规范,没有别的内容,但Eevee的指南非常棒。 - Esteis
13
对于我们这些不熟悉的人来说,执行pip3 install pyyaml命令可以让它准备好被导入到Python脚本中。 - user8675309
8
请注意,YAML只有在非常简单的情况下才会友好,它默认具有大量问题,甚至可能存在不安全特性。尝试使用https://hitchdev.com/strictyaml/作为默认安全轻量级替代方案。 - Gringo Suave
3
请参见Munch,https://dev59.com/8a7la4cB1Zd3GeqPicC3 import yaml; from munch import munchify; f = munchify(yaml.load(…)); print(fo.d.try) - Hans Ginzel
@HansGinzel 你应该单独回答,因为你所建议的方法更容易使用。 - Begoodpy

175
我发现这个是最有用和易于使用的 https://wiki.python.org/moin/ConfigParserExamples 你只需要创建一个名为"myfile.ini"的文件,像这样:
[SectionOne]
Status: Single
Name: Derek
Value: Yes
Age: 30
Single: True

[SectionTwo]
FavoriteColor=Green
[SectionThree]
FamilyName: Johnson

[Others]
Route: 66

并且获取数据如下:
>>> import ConfigParser  # For Python 3 use the configparser module instead (all lowercase)
>>> Config = ConfigParser.ConfigParser()
>>> Config
<ConfigParser.ConfigParser instance at 0x00BA9B20>
>>> Config.read("myfile.ini")
['c:\\tomorrow.ini']
>>> Config.sections()
['Others', 'SectionThree', 'SectionOne', 'SectionTwo']
>>> Config.options('SectionOne')
['Status', 'Name', 'Value', 'Age', 'Single']
>>> Config.get('SectionOne', 'Status')
'Single'

47
Python 3使用configparser模块(全小写)代替。 - Roland
3
这是最快、最清晰、最易于实现的解决方案,因为没有实现,只需使用。 :) 谢谢! - Aleksandar
3
这是否支持嵌套字典,就像问题中所问的那样? - Jakub Bláha
2
@JakubBláha 不。 - cambunctious
这个程序不识别数据类型,因此将所有值解释为字符串。Yaml 和 Json 不会有这个缺点。 - Timo Richter

68

Yaml和Json是最简单和最常用的文件格式,用于存储设置和配置。可以使用PyYaml解析yaml。自Python 2.5起,Json已经成为Python的一部分。Yaml是Json的超集。Json将解决大多数用例,除了需要转义的多行字符串。Yaml也可以处理这些情况。

>>> import json
>>> config = {'handler' : 'adminhandler.py', 'timeoutsec' : 5 }
>>> json.dump(config, open('/tmp/config.json', 'w'))
>>> json.load(open('/tmp/config.json'))   
{u'handler': u'adminhandler.py', u'timeoutsec': 5}

18
尽管两者有些相似,但与yaml相比,json不太易读。由于示例配置实际上是有效的yaml格式,我建议强调使用yaml而不是json。 - Benson
28
使用 "json.dump(config, fp, sort_keys=True, indent=4)" 可以提高可读性。 - phobie
4
一个简单的Python类以RAII方式从JSON文件中加载其数据成员。 - Hope

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接