跨平台python模块,通过本地子系统(如windows registry或nsuserdefaults)存储应用程序配置。

nativeconfig的Python项目详细描述


TravisAppVeyorCoverageUpdatesPython 3PyPI

跨平台应用程序的开发人员在需要与系统交互时常常会遇到问题。 配置文件也不例外,因为每个流行的操作系统都有自己的格式和准则。

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三个简单规则:

  1. 从最旧版本检查到最新版本
  2. 用户if,而不是elif
  3. 在末尾呼叫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命令。

欢迎加入QQ群-->: 979659372 Python中文网_新手群

推荐PyPI第三方库


热门话题
java Spring框架服务单元测试   在Java中遍历hashmaps的hashmap以检索字符串值   如何使用CodeQL检查Java注释是否具有特定属性?   java为什么在Spring Boot中访问此资源而不是登录弹出窗口需要始终获得完全身份验证   处理将多集计数转换为列表的过程   java另一个线性布局,没有出现按钮   eclipse Java映像加载未显示在jar中   java Junit类无法加载基本测试类ApplicationContext   java如何在main中使用my getvalues()方法打印列表   java Sonar,S128:切换案例应该以无条件的“中断”语句结束,而不是继续   java从socket读取字符串错误连接重置错误   java使用新数据刷新任意图表饼图   java通过异步运行lambda访问方法参数   java错误的结果一旦我处理try and catch