10

我从离开我们公司的开发人员那里收到了一个项目。不太复杂,但看起来不是很好。所以这是一个问题:应用程序有一些模块,一个是存储一些应用程序的“设置”。选项(不是所有可能的选项,让我们说两个:foobar)。当应用程序启动时,它从命令行读取选项(使用 argparse):

parser.add_argument('--foo', action='store_true')
parser.add_argument('--bar', action='store_true')
parser.add_argument('--baz', action='store_true')

然后它执行了这个讨厌的事情:

for name, val in parser.parse_args(sys.argv[1:])._get_kwargs():
    setattr(sys.modules['settings'], name, val)

第一:我认为这是肮脏的,非pythonic hack。其次,使用这样的代码很不方便,因为当我需要使用时settings.baz,IDE 抱怨它不存在。此 hack 的目的是使从命令行解析的选项在应用程序中进一步使用的所有模块中可用。

我正在考虑类似单例模​​式的东西,但我只在 PHP 中使用过一次,不知道这在 python 中是否正确。即使是这样,有人可以举个例子吗?

我是python和SO的菜鸟,请善待我:)谢谢。

ps 对于我的英语可能出现的错误,我深表歉意

4

2 回答 2

10

Python 中的模块单例对象,使用一个来存储其他模块使用的设置将是非常 Pythonic

“讨厌的东西”的第二行只是设置一个名为的模块的属性,settings所以还不错。更糟糕的是第一行的一部分,它正在访问返回的对象_get_kwargs()的私有属性,以获取从命令行解析的设置的名称和值。一个稍微好一点的方法可能是这样的:argparse.Namespaceparser.parse_args()

import settings  # possibly empty .py file

for name, val in vars(parser.parse_args(sys.argv[1:])).iteritems():
    setattr(settings, name, val)

但是,这不会解决您的 IDE 问题,因为 IDE 不知道动态添加的设置的名称。解决此问题的一种简单方法是在模块中使用某种默认值定义所有可能的属性,settings.py而不是使用空属性。

模块第一次被import编辑时,它的条目被添加到sys.modules字典中,其名称作为键,实例types.ModuleType作为值。随后import的 s 将首先检查它的条目是否已经存在,如果存在,将跳过重新加载文件——这就是我声称它们基本上是单例对象的原因。对其属性所做的修改将立即对已导入或之后导入它的其他模块可见,因此它通常是应用程序中良好的数据共享机制。

于 2013-05-22T18:49:27.143 回答
0

看看这个Config(一个分层的、易于使用的、强大的 Python 配置模块)

详细的文档和示例

于 2013-05-22T16:02:26.283 回答