使用ConfigParser编写配置文件相比普通python.py文件有什么好处?
我已经使用ConfigParser模块来写配置文件有一段时间了。不过,最近我突然想到,为什么不直接用纯Python来做呢?比如说,这里有一个示例配置文件:
[parameters]
# Host
host = stackoverflow.com
port = 22
要把这些值读到我的代码里,我可以这样做:
import ConfigParser
config = ConfigParser.SafeConfigParser()
config.read('host.cfg')
host = config.get('parameters', 'host')
port = config.get('parameters', 'port')
另一方面,如果我有一个这样的配置文件:
# Host
host = 'stackoverflow.com'
port = 22
在我的主代码中,我可以这样做:
from host_cfg import *
那么,使用ConfigParser模块有什么好处呢?每种方法的优缺点是什么呢?
3 个回答
使用Python文件的方法有一个潜在的缺点,就是用户可以在文件里放入任意代码,这些代码会在你的应用程序中执行。正如S. Lott在评论中提到的(当时我对这个问题的警告比较强烈),通常这不是个大问题,因为用户(或者黑客)通常可以访问你的整个源代码,随便改动。
不过,我可以想象一些情况,这种方法可能会导致新的安全隐患,比如当主要的脚本文件只有系统管理员可以写,而每个用户的配置文件是唯一可以被普通用户编辑的文件。在这种情况下,除非你非常确定你的代码永远不会在这样的环境中运行,否则我不建议使用Python模块的方法。很多人认为“不要执行用户提供的代码”是个很好的实践,确实有其道理。
执行配置文件也会让处理错误变得麻烦。如果用户在文件里写错了语法,你肯定想要捕捉到这个错误,你可以通过在import
周围加上try
来轻松做到,但错误之后的代码就不会执行了。在配置文件中,通常会继续解析下一行,所以用户最多只会漏掉一个设置,而不是(比如)一半的设置。虽然有办法让Python模块更像配置文件(例如,你可以把文件当作文本读取,然后用exec()
逐行执行),但如果你需要做任何处理,使用ConfigParser
会更简单。
如果尽管有这些问题,你仍然想在配置文件中使用Python语法,你可以使用ast
模块(查看literal_eval()
函数)。
ConfigParser 是用来解析简单的、扁平的配置数据的工具。导入一个 Python 模块会运行代码。而对于配置文件来说,我们需要的是数据,而不是代码。这就解决了。
再详细一点说:代码可以做很多事情,但也更容易出问题,尤其是当非程序员修改的时候(试着跟那些修改 .ini
文件的人解释,他们需要使用匹配的引号和转义字符……)。另外,代码还可能和你应用的其他部分产生命名空间冲突(特别是当你使用 import *
的时候)。还有一个相关的概念可以参考一下,就是最小权限原则。
使用ConfigParser模块我能得到什么好处呢?
它可以和Windows的.ini文件兼容,这让一些人觉得很开心。
每种方法的优缺点是什么?
ConfigParser的语法比较有限,有些简单的事情用起来会显得很复杂。比如看看logging
的例子。
而Python的语法更简单,使用起来也更方便。没有安全隐患,因为没有人会浪费时间去破解配置文件,大家更倾向于直接攻击你的源代码。实际上,他们甚至可以攻击大部分内置的Python库。更别提,他们还可以对Python解释器本身下手。
总之,没人会去浪费时间破解配置文件,因为在你的应用源代码中有很多更简单的漏洞可以利用。