我正在开发一个相对较大的Python应用程序,并且我希望将几个资源保留为可在多个不同模块中访问的全局变量。这些值类似于版本号,版本日期,全局配置以及一些资源的静态路径。我还包含一个DEBUG
标志,该标志由命令行选项设置,这样我就可以在调试模式下运行我的应用程序而无需完整的环境。
我导入的值我已经小心翼翼地确保在运行程序的过程中不会改变的值,并且我已将它们记录为全局常量变量,不应该是感动。我的代码看起来基本上像
# Main.py
import wx
from gui import Gui
DEBUG = False
GLOBAL_CONFIG = None
VERSION = '1.0'
ICON_PATH = 'some/path/to/the/app.ico'
def main():
global DEBUG, GLOBAL_CONFIG
# Simplified
import sys
DEBUG = '--debug' in sys.argv
GLOBAL_CONFIG = load_global_config()
# Other set-up for the application, e.g. setting up logging, configs, etc
app = wx.App()
gui = Gui()
app.MainLoop()
if __name__ == '__main__':
main()
# gui.py
import wx
from __main__ import DEBUG, GLOBAL_CONFIG, ICON_PATH
import controller
class Gui(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, None)
icon = wx.Icon(ICON_PATH, wx.BITMAP_TYPE_ICO)
self.SetIcon(icon)
# Always make a copy so we don't accidentally modify it
conf = GLOBAL_CONFIG.copy()
self.controller = controller.Controller(conf)
# More setup, building the layout, etc
# controller.py
from __main__ import DEBUG
import logging
log = logging.getLogger('controller')
class Controller(object):
def __init__(self, conf):
if DEBUG:
log.info("Initializing controller in DEBUG mode")
self.conf = conf
# Other setup ...
这显然远远落后于我的应用程序实际上,并且忽略了错误处理,文档以及基本上所有实现细节。
现在,我seen it said这是一个坏主意,但没有解释原因。搜索" python import __main __"的变体时搜索结果最多。关于if __name__ == '__main__'
是什么的问题,很难找到关于这个主题的一些可靠信息。到目前为止,我没有遇到任何问题,而且实际上非常方便。
所以这被认为是优秀的Python实践,还是有理由避免这种设计?
答案 0 :(得分:23)
我认为有两个主要(哈哈)原因可能会规定避免这种模式。
如果您完全掌控了该应用程序,并且您的功能将永远不会有其他入口点或其他用途,并且您确定不会注意到这种模糊性,我不会想到有{em>目标的原因导致from __main__ import foo
模式不好。我个人不喜欢它,但同样,基本上是出于上述两个原因。
我认为更强大/开发人员友好的解决方案可能是这样的,创建一个专门用于保存这些超全局变量的特殊模块。然后,您可以导入模块,并在需要设置时随时参考module.VAR
。本质上,只需创建一个特殊的模块命名空间,用于存储超全局运行时配置。
# conf.py (for example)
# This module holds all the "super-global" stuff.
def init(args):
global DEBUG
DEBUG = '--debug' in args
# set up other global vars here.
然后你会更像这样使用它:
# main.py
import conf
import app
if __name__ == '__main__':
import sys
conf.init(sys.argv[1:])
app.run()
# app.py
import conf
def run():
if conf.DEBUG:
print('debug is on')
请注意使用conf.DEBUG
而不是from conf import DEBUG
。这种结构意味着你可以在程序的生命周期内改变变量,并将这种变化反映在其他地方(显然假设一个线程/进程)。
另一个好处是,这是一个相当普遍的模式,因此其他开发人员将很容易认识到它。它很容易与各种流行应用程序使用的settings.py
文件(例如django
)相媲美,但我避免使用该特定名称,因为settings.py
通常是一堆静态对象,而不是运行时参数的命名空间。例如,上述配置命名空间模块的其他好名称可能是runtime
或params
。
答案 1 :(得分:6)
这样做需要违反PEP8,指定
导入总是放在文件的顶部,就在任何模块注释和文档字符串之后,以及模块全局变量和常量之前。
为了gui.py
成功导入__main__.DEBUG
,您必须在 DEBUG
之前设置import gui
的值。