跨平台python模块,通过本地子系统(如windows registry或nsuserdefaults)存储应用程序配置。
nativeconfig的Python项目详细描述
跨平台应用程序的开发人员在需要与系统交互时常常会遇到问题。 配置文件也不例外,因为每个流行的操作系统都有自己的格式和准则。
nativeconfig以一种优雅和python的方式解决了这个问题:
importosfromnativeconfigimportPreferredConfig,StringOption,IntOptionclassMyConfig(PreferredConfig):CONFIG_VERSION=__version__REGISTRY_PATH=r'Software\MyApp'JSON_PATH=os.path.expanduser('~/.config/MyApp/config')first_name=StringOption('FirstName')last_name=StringOption('LastName')age=IntOption('Age')
将配置存储在windows上的registry、mac os x上的nsuserdefaults(如果pyobjc-core模块可用)和其他任何地方的json格式文件中。
缓存
所有平台的实现都支持缓存,从而最小化对后端的访问。特定的值只有在不知道缓存时才被读取 如果它和缓存的不一样就写。
只要声明您的子类,ALLOW_CACHE
设置为True
:
classMyConfig(PreferredConfig):CONFIG_VERSION=__version__ALLOW_CACHE=TrueREGISTRY_PATH=r'Software\MyApp'JSON_PATH=os.path.expanduser('~/.config/MyApp/config')first_name=StringOption('FirstName')last_name=StringOption('LastName')
您还可以为每个选项设置此设置,方法是将allow_cache
设置为True
来声明这些设置。
json作为通用格式
在某些时候,您需要提供公共接口(例如cli或api)来编辑应用程序的配置。 因此,有一些方法可以将每个选项单独或整个配置转换为json:
classMyConfig(PreferredConfig):CONFIG_VERSION=__version__REGISTRY_PATH=r'Software\MyApp'JSON_PATH=os.path.expanduser('~/.config/MyApp/config')first_name=StringOption('FirstName')last_name=StringOption('LastName')MyConfig.get_instance().get_value_for_option_name('FirstName')# will return JSON version of first_name's valueMyConfig.get_instance().snapshot()# will return a JSON dictionary of all optionsMyConfig.get_instance().restore_snapshot(user_edited_snapshot)# will update options with from user-edited JSON
自省
当你绕过lib代码中可能存在的缺陷时总是很酷的。所以你有了它:basicconfig和basicoption的api被精心设计成可破解的。 特别是,配置的attibutes可以通过分组在“内省”部分下的一组方法或者通过玩basicconfig.u ordered\u选项来轻松检查。 直接的。你没有误读,选项已经按定义顺序排列,甚至是子类化,甚至是重写!
classMyConfig(PreferredConfig):CONFIG_VERSION=__version__REGISTRY_PATH=r'Software\MyApp'JSON_PATH=os.path.expanduser('~/.config/MyApp/config')first_name=StringOption('FirstName')last_name=StringOption('LastName')MyConfig.get_instance().get_value_for_option_name('FirstName')# will return python value of the FirstName optionMyConfig.get_instance().get_raw_value_for_option_name('FirstName')# will return raw value of the FirstName optionMyConfig.get_instance().get_json_value_for_option_name('FirstName')# will return JSON encoded value of the FirstName option
版本控制
每个开发人员都将面临的任务。幸运的是nativeconfig有一切可以帮助你!
每个配置都有版本,默认为1.0。它的版本以“config version”名称存储在配置后端中 可以通过修改config_version_option_name类变量进行更改。
您应该在自定义子类中通过定义config_version变量来重写它。通常最有意义的值是__version__变量。
每次初始化配置时,都会调用migrate
方法。基类的实现只需将“configversion”(或您称之为configversion)选项的值更新为实际值。
合理,但不够充分。让我们看看我们能做些什么:
classMyConfig(PreferredConfig):CONFIG_VERSION=__version__REGISTRY_PATH=r'Software\MyApp'JSON_PATH=os.path.expanduser('~/.config/MyApp/config')first_name=StringOption('FirstName')last_name=StringOption('LastName')defmigrate(self,version):ifversionisNone:# Either called for the very first time OR user's backed is broken because it lacks value of the ConfigVersion option.passifversion<=<newerversion>:# Obviously <= will not work for strings. You should use your own comparison function that follows you versioning guidelines.passifversion<=<newestversion>:# Version should be checked starting from the oldest to the current so you can gracefully migrate even the oldest user's config.# `if` is used instead of `elif` for the same reason: you may need to migrate user's data through multiple versions of the config file.passifversion<=<mostrecentversion>:passsuper().migrate(version)# always call base class implementation at the end!
tl;dr三个简单规则:
- 从最旧版本检查到最新版本
- 用户
if
,而不是elif
- 在末尾呼叫super
错误恢复
当用户群庞大时,各种奇怪的问题就会发生。选项的意外值可能是最常见的。 而nativeconfig拥有从这些错误中恢复所需的一切!
每当配置无法反序列化值或反序列化值是意外的(例如,您希望float bug获得路径)
调用resolve_value
方法。默认实现记录错误并返回默认值。如果这还不够
或者,与使用默认方法相比,您对如何恢复有更好的了解,您应该重写此方法:
classMyConfig(PreferredConfig):CONFIG_VERSION=__version__REGISTRY_PATH=r'Software\MyApp'JSON_PATH=os.path.expanduser('~/.config/MyApp/config')first_name=StringOption('FirstName')last_name=StringOption('LastName')defresolve_value(self,exc_info,name,raw_or_json_value,source):ifname=='FirstName':# E.g. restore value from Cloud-stored credentials.pass
非常基本:您已经提取了发生问题的exc_信息(validationerror或反序列化error)、选项名称、raw或json值以及 解释错误发生位置的来源。
调试
在某些地方使用了warn
模块,因此建议您按照docs中的说明,通过将所有警告转换为错误来调试应用程序。
各种日志被写入nativeconfig
记录器。可以通过提高级别来增加详细程度。
测试
要运行测试,请使用python -m test
命令。