首先,情景。我有一个模块config.py:
DEBUG = False # Set to True with --debug option
另一个使用它的模块do.py:
from config import DEBUG
def do_something():
if DEBUG:
print 'Debug...'
print 'do something'
在main.py中:
import config
import do
import sys
if __name__ == '__main__':
if len(sys.argv) > 1 and sys.argv[1] == '--debug':
config.DEBUG = True
do.do_something()
现在,当我运行它时:
$ python2.7 main.py --debug
do something
所以在do_something()
中,DEBUG
False 。
拥有这样的配置标志的最佳方式是:
答案 0 :(得分:1)
解决第1点,我可以这样写do.py:
import config
def do_something():
if config.DEBUG:
print 'Debug...'
print 'do something'
但现在config.DEBUG
并不简洁(第2点)。
或者我可以像这样编写config.py:
class Debug(object):
_DEBUG = False
def __call__(self):
return self._DEBUG
def set(self, debug):
self._DEBUG = debug
DEBUG = Debug()
但这样可以避免像这样的简单错误:
>>> import config
>>> config.DEBUG()
False
>>> from config import DEBUG
>>> DEBUG()
False
>>> DEBUG.set(True)
>>> DEBUG()
True
>>> DEBUG.set(False)
>>> DEBUG()
False
>>> if DEBUG: print 'Oops'
...
Oops
违反了第3点。
那么还有更好的解决方案吗?
答案 1 :(得分:1)
你拥有的可能是最好的方式。通常,Python中的变量属于某处,而DEBUG
属于config
,而不是其他任何地方。如果你想将它导入另一个模块,那很好,但你想明确地做,就像你正在做的那样,而不是通过魔术。
值得注意的是,如果您使用DEBUG
进行的唯一事情是if DEBUG: print <stuff>
,那么使用函数可能会更好:
config.debug(stuff)
此时,您可能需要查看logging
,而不是重新发明轮子的三分之一,并希望您不需要另外三分之二。
但是,如果你真的想要“工作,简洁,安全”而不考虑pythonicity或可移植性,还有一个选择:__builtin__
模块(在Python 3.x中重命名为builtins
。) / p>
在main.py中:
import __builtin__
import do
import sys
if __name__ == '__main__':
__builtin__.DEBUG = len(sys.argv) > 1 and sys.argv[1] == '--debug'
do.do_something()
在do.py中,无需导入任何内容:
def do_something():
if DEBUG:
print 'Debug...'
print 'do something'
当然,如果您编写另一个脚本,例如test.py
,导入do
而不导入main
,则会引发NameError
。但是,如果您在导入from config import DEBUG
之前尝试执行此操作,则会从config.DEBUG
或main
收到相同的错误,因此情况并非如此。
为什么这样做?来自文档:
CPython实现细节:大多数模块都有名称
__builtins__
(注意's')作为其全局变量的一部分。__builtins__
的值通常是此模块或此模块的__dict__
属性的值。由于这是一个实现细节,因此Python的替代实现可能不会使用它。
特别是,每当你import
一个模块或运行一个顶级脚本时,除非你用导入钩子做了一些奇怪的事情,执行模块字节码的exec
将确保这个发生。这意味着,只要模块不影响DEBUG
(当然总是可能)或者使用其全局变量,DEBUG
将永远存在于内置字典中。 (如果您exec
自己的任何代码明确构建types.ModuleType
,并传递显式globals
而不是继承它,那么您必须记住做同样的事情,但是希望这不是问题。)
它至少适用于PyPy 2.x和3.x以及Jython 2.5和2.7。除此之外?谁知道;它不能保证。
答案 2 :(得分:0)
我想值得注意的是
from config import DEBUG
在您设置之前导入DEBUG
(False
)的值。稍后当您更改它时,您的do
模块仍指向旧的False
值。如果你想让它更具动态性,你可以在配置中使用一个函数:
# config.py
is_debug = False
def debug():
return is_debug
然后在do.py
# do.py
from config import debug
def do_something():
if debug():
print 'Debug...'
print 'do something'