我正在看几个python项目。几乎每个好的python项目通常都有一个 app.conf 或 app.ini 文件用于配置管理。之后,他们使用.py
模块之类的东西从 app.conf 文件中提取配置信息。最后,他们不得不使用[BREED]
beagle=dog
ragdoll=cat
deilenaar=rabbit
cockatoo=parrot
模块中的值。
让我们举个例子
#!/usr/bin/env python
#-*- coding: utf-8 -*-
import configparser
config = configparser.ConfigParser()
config.read('app.conf')
print(config['BREED']['cockatoo']) # prints parrot
#!usr/bin/env python
# -*- coding: utf-8 -*-
config = {'BREED': {'beagle': 'dog',
'ragdoll': 'cat',
'deilenaar': 'rabbit',
'cockatoo': 'parrot'}}
print(config['BREED']['cockatoo']) # prints parrot
那么为什么不使用字典并使用该字典而不是以下内容。
config
如果我们需要全局使用__init__.py
,那么我们会将变量放在/* Directive template */
<md-button class="md-button-toggle" ng-click="vm.toggle()">
{{ section.text | translate }}
</md-button>
<ul ng-show="isOpen()" class="menu-toggle-list">
<li ng-repeat="subItem in section.subItems">
{{ subItem.text | translate }}
<menu-link section="subItem"></menu-link>
</li>
</ul>
/* Directive Code */
...
return {
restrict: 'AE',
template,
replace: true,
scope: {
section: '=',
isOpen: '&'
},
link(scope, element) {
$timeout(() => {
const $element = element;
scope.vm.toggle = function () {
console.log(scope.$parent.isOpen());
};
scope.isOpen = function () {
return $element.isOpen(scope.section);
};
scope.toggle = function () {
$element.toggleOpen(scope.section);
};
});
}
}
/* in your view, you can call controller fn */
<menu-toggle section="navItem" is-open="isOpen()" ng-if="navItem.type === 'toggle'"></menu-toggle>
的包的根目录中。这样我们就不用再阅读 app.conf 文件了。
我相信使用 app.conf 文件是有充分理由的。那是什么原因?
答案 0 :(得分:1)
从配置文件中读取时,程序员可以选择如何处理文件格式化中的错误。无法解析特定的行?分配默认值。想要宽恕并接受没有收尾报价的字符串?去吧。
另一方面,Python模块全有或全无。如果文件的语法不完美,那么你什么也得不到
答案 1 :(得分:0)
因此,用户无需编辑源代码即可更改.conf
文件中的值。还允许将设置保存到.conf
并稍后阅读,而无需编辑源文件。
答案 2 :(得分:0)
安全。
我同意您的观点,但安全性无法处理 config.py
,除非使用包装器,在这种情况下可以称为 config_parser.py
假设在您的代码中导入了 config.py
。
from config.dir import config
这一行执行 config.py
!
这意味着任何攻击者都可以在那里做任何事情,可能具有更高的权限。
我有足够的理由不这样做。
这是我的样板配置
class ConfigProvider(object):
_config = None
@staticmethod
def get_config():
if ConfigProvider._config is None:
ConfigProvider._config = ConfigParser(config_path).parse()
return ConfigProvider._config
class ConfigParser(object):
def __init__(self, config_path):
self._config_path = config_path
def parse(self):
parsed = None
with open(self._config_path, 'r') as stream:
try:
# https://stackoverflow.com/questions/2352181/how-to-use-a-dot-to-access-members-of-dictionary
parsed = Map(yaml.safe_load(stream))
except yaml.YAMLError as exc:
traceback.print_exc(exc)
return parsed
class Map(dict):
# https://stackoverflow.com/questions/2352181/how-to-use-a-dot-to-access-members-of-dictionary
"""
Example:
m = Map({'first_name': 'Eduardo'}, last_name='Pool', age=24, sports=['Soccer'])
"""
def __init__(self, *args, **kwargs):
super(Map, self).__init__(*args, **kwargs)
for arg in args:
if isinstance(arg, dict):
for k, v in arg.items():
self[k] = v
if isinstance(v, dict):
self[k] = Map(v)
if kwargs:
# for python 3 use kwargs.items()
for k, v in kwargs.items():
self[k] = v
if isinstance(v, dict):
self[k] = Map(v)
def __getattr__(self, attr):
return self.get(attr)
def __setattr__(self, key, value):
self.__setitem__(key, value)
def __setitem__(self, key, value):
super(Map, self).__setitem__(key, value)
self.__dict__.update({key: value})
def __delattr__(self, item):
self.__delitem__(item)
def __delitem__(self, key):
super(Map, self).__delitem__(key)
del self.__dict__[key]
def __getstate__(self): # required for successful pickling
return self.__dict__
def __setstate__(self, d): # required for successful pickling
self.__dict__.update(d)
config = ConfigProvider.get_config()
用户总是只需要一行就可以获取他们的配置。
当然不如 .py 方便,但安全性很重要。
注意 yaml 上的 safe_load
。