我收到了离开公司的开发人员的项目。不太复杂,但看起来不太好。
所以这是一个问题:
应用程序有一些模块,一个是存储某些应用程序的“设置”。选项(并非所有可能的选项,仅举两个:foo
和bar
)。
启动应用程序时,它从命令行读取选项(使用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黑客。第二,使用这样的代码简直不方便,因为当我需要使用settings.baz
时,IDE会抱怨它不存在。
此hack的目的是使命令行解析的选项在应用程序中进一步使用的所有模块中可用。
我正在考虑像单例模式这样的东西,但我只在PHP中使用过一次,并且不知道python中是否有这个正确的解决方案。即使它是,有人可以展示例子吗?
我是python中的菜鸟,在SO上,请善待我:) 感谢。
P.S。对不起,我的英语可能出错了
答案 0 :(得分:6)
Python 中的模块是单例对象,使用一个来存储其他模块使用的设置将是一个非常Pythonic
“讨厌的东西”的第二行只是设置名为settings
的模块的属性,所以并没有那么糟糕。更糟糕的是第一行的_get_kwargs()
部分访问argparse.Namespace
返回的parser.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
将首先检查它的条目是否已经存在,并且如果有的话将跳过重新加载文件 - 这就是我声称它们基本上是单例对象的原因。对其属性进行的修改将立即显示给已导入它的其他模块或之后执行此操作,因此它通常是应用程序中的良好数据共享机制。
答案 1 :(得分:0)