Python程序存储设置的官方方法是什么?

67

Django 使用真正的 Python 文件来进行设置,Trac 使用一个 .ini 文件,而一些其他的软件使用 XML 文件来保存这些信息。

在这些方法中,是否有一种方法被 Guido 和/或 Python 社区认可得更多?


2
根据维基百科,“ini”文件曾经在Windows中占主导地位,但现在已被弃用。因此,在我看来,你应该跳过这个选择。 - WhyNotHugo
上面的链接已经失效。微软提供了新的链接:为什么INI文件被弃用,改用注册表? 日期为2007年11月26日。 - pabouk - Ukraine stay strong
14个回答

39

根据主要的目标受众而定。

如果是程序员会更改该文件,则可以使用像settings.py这样的python文件。

如果是最终用户,则考虑使用ini文件。


35
一个典型的 settings.py 文件是什么样子? - Hamish Grubijan
3
我认为他在提到 Django 的 settings.py 文件。这是一个有效的 Python 文件,包含字符串、元组、列表和其他变量的声明。 - pcx
3
我同意第一部分,但如果最终用户需要更改它,你可以使用ConfigParser来读取。 - WhyNotHugo
我知道这个话题很老了,但是一个settings.py文件如何像一个.ini文件一样存储配置以便在运行时读取呢?一个settings.py让我想到会有一个Settings类来协调设置的设置和取消设置,但是它们将如何存储呢?目前我没有使用settings.py文件,而是使用一个.env文件来存储配置选项,因为.ini文件看起来很容易被用户修改。无论哪种方式,使用.env感觉不对,因为它不够结构化,也可能导致用户错误修改。 - dsenese
我知道这个话题很老了,但是一个 settings.py 文件怎么样才能像一个 .ini 文件一样存储配置以便在运行时读取呢?一个 settings.py 让我想到会有一个 Settings 类来协调设置的设置和取消设置,但是它们会被存储在哪里呢?目前我没有使用 settings.py 文件,而是使用一个 .env 文件来存储配置选项,因为一个 .ini 文件看起来很容易被用户修改。无论哪种方式,使用 .env 都感觉不对,因为它不够结构化,也可能导致用户错误修改。 - undefined

32

正如许多人所说,没有"官方"的方法。但是,有很多选择。今年在PyCon上有一个关于许多可用选项的演讲


6
@mac,我找到了:http://blip.tv/pycon-us-videos-2009-2010-2011/a-configuration-comparison-in-python-2006550 - utdemir
@utdemir - 谢谢,我用你的链接更新了原始答案,删除了我的原始评论... - mac

20

我不确定这是否被认为是“官方”的,但它在标准库中:14.2. ConfigParser — 配置文件解析器

显然,这并不是一个通用的解决方案。只需使用感觉最适合任务的内容,没有任何必要的复杂性(尤其是图灵完备!考虑自动或GUI配置程序)。


1
JSON也是标准库中的一部分,还包括各种XML处理模块。 - SilentGhost
7
当然,JSON是标准格式,但这个模块之所以被称为“配置文件解析器”,是有原因的。我认为它非常适合读写,并且对于初学者和非初学者用户来说都很容易理解。 - WhyNotHugo
@SilentGhost,JSON格式不太适合用于可由人类编辑的配置文件。原因如下:1.它不支持注释。2.许多括号和双引号可能会让人类编辑感到困惑。 - pabouk - Ukraine stay strong

16

12
根据文档,“shelve”模块由pickle支持,因此从不受信任的来源加载货架是不安全的。与pickle一样,加载货架可以执行任意代码。如果这个问题旨在引导新手,每个人都应该指向configparser模块,否则可以指向JSON或自定义文件。INI文件节比JSON更具定义性(可读性),即使您美化了其代码。[]方括号添加了一点粗体的感觉,所以节很容易观察。 - m3nda

12

还有一个选项,PyQt。Qt使用QSettings类以平台无关的方式存储设置。在Windows下,它在注册表中使用,在Linux中则将设置存储在隐藏的conf文件中。QSettings工作得非常好,而且非常顺畅。


8
据我所知,没有神圣的解决方案。存储应用程序设置的方法没有对错之分,无论是xml、json还是各种类型的文件都可以,只要你感觉舒适。对于Python,我个人使用pypref,它非常简单、跨平台和直接。 pypref非常有用,因为可以存储静态和动态设置和首选项...
from pypref import Preferences

#  create singleton preferences instance
pref = Preferences(filename="preferences_test.py")

# create preferences dict
pdict = {'preference 1': 1, 12345: 'I am a number'}

# set preferences. This would automatically create preferences_test.py 
# in your home directory. Go and check it.
pref.set_preferences(pdict)

# lets update the preferences. This would automatically update 
# preferences_test.py file, you can verify that. 
pref.update_preferences({'preference 1': 2})

# lets get some preferences. This would return the value of the preference if
# it is defined or default value if it is not.
print pref.get('preference 1')

# In some cases we must use raw strings. This is most likely needed when
# working with paths in a windows systems or when a preference includes
# especial characters. That's how to do it ...
pref.update_preferences({'my path': " r'C:\Users\Me\Desktop' "})

# Sometimes preferences to change dynamically or to be evaluated real time.
# This also can be done by using dynamic property. In this example password
# generator preference is set using uuid module. dynamic dictionary
# must include all modules name that must be imported upon evaluating
# a dynamic preference
pre = {'password generator': "str(uuid.uuid1())"}
dyn = {'password generator': ['uuid',]}
pref.update_preferences(preferences=pre, dynamic=dyn)

# lets pull 'password generator' preferences twice and notice how
# passwords are different at every pull
print pref.get('password generator')
print pref.get('password generator')

# those preferences can be accessed later. Let's simulate that by creating
# another preferences instances which will automatically detect the 
# existance of a preferences file and connect to it
newPref = Preferences(filename="preferences_test.py")

# let's print 'my path' preference
print newPref.get('my path')

pypref 真是太棒了。非常简单和直接的使用方式(这让我想起了 Android 的 SharedPreferences,也许就是因为这个原因)。祝贺你们做得很好! - dentex
3
很遗憾,在Python 3中不受支持。 - Anatoly Alekseev

6

其中一种最简单的方法是使用json模块。请按照下面的细节将文件保存在config.json中。

将数据保存在json文件中:

{

    "john"  : {
        "number" : "948075049" , 
        "password":"thisisit" 
    }    
}

从json文件中读取:

import json

#open the config.json file 

with open('config.json') as f:
    mydata = json.load(f) ; 

#Now mydata is a python dictionary 

print("username is " , mydata.get('john').get('number') , " password is " , mydata.get('john').get('password')) ;

1
请注意,mydata.get('john').get('number') 不是一个好的代码。如果数据中没有 john 键,则 mydata.get('john') 将返回 None,而 .get('number') 将引发异常。 使用 .get 假定您希望优雅地处理缺少的数据;因此最好这样做: mydata.get('john', {}).get('number') - 这不会导致异常,除非 mydata 本身不是一个 dict - MarSoft

6

我不确定是否存在官方的方法(Python之禅中没有提到 :) ),但我倾向于使用Config Parser模块,我认为你会发现这很常见。我更喜欢它而不是Python文件方法,因为你可以写回去并动态重新加载。


4

这取决于您的配置有多复杂。如果您只是进行简单的键值映射,并希望能够使用文本编辑器编辑设置,那么我认为 ConfigParser 是最好的选择。

如果您的设置很复杂,包括列表和嵌套数据结构,我建议使用 XML 或 JSON 并创建一个配置编辑器。

对于真正复杂的事情,其中最终用户不需要经常更改设置或更加可信任,只需创建一组 Python 类并评估 Python 脚本以获取配置即可。


2
对于 Web 应用程序,我喜欢使用操作系统环境变量:os.environ.get('CONFIG_OPTION')。这在处理不同部署之间的设置时特别有效。您可以在这里阅读有关使用环境变量的理由:http://www.12factor.net/config。当然,这仅适用于只读值,因为对环境的更改通常不是持久性的。但如果您不需要写入访问权限,则它们是一个非常好的解决方案。

还不错,但是当需要设置大量变量时,用Django的方式可能更方便:将它们存储在一个文件中,并根据单个环境变量(在Django中使用DJANGO_SETTINGS_MODULE)设置不同的文件。这样你就可以拥有动态和可写的值了。 - danius
如果您正在使用此方法,则可能还想查看 https://github.com/theskumar/python-dotenv - smilly92

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