从单个导入访问python应用程序中的全局变量

从单个导入访问python应用程序中的全局变量,python,global-variables,Python,Global Variables,因此,我尝试使用python解释器作为服务器端python应用程序的CLI。然而,在加载python模块时,我得到了一个我没有预料到的行为 我有两个python文件和一个缓存文件: Main.py Config.py Cache.json 因此,当导入并运行Main时,Main()函数会导入Configs,然后调用一个函数来初始化Config。初始化配置时,根据我运行的环境,从Cache.json加载一些全局变量。下面是一个.py的简化示例 #Main.py import Config def

因此,我尝试使用python解释器作为服务器端python应用程序的CLI。然而,在加载python模块时,我得到了一个我没有预料到的行为

我有两个python文件和一个缓存文件:

Main.py
Config.py
Cache.json

因此,当导入并运行Main时,Main()函数会导入Configs,然后调用一个函数来初始化Config。初始化配置时,根据我运行的环境,从Cache.json加载一些全局变量。下面是一个.py的简化示例

#Main.py
import Config

def main():
    """Initialize Python Application"""
    Config.init()


if __name__ == "__main__":
    main()

现在理论上,如果我在python解释器中调用以下命令:

>>>from Main import main
>>>main()
Config应该由main()导入,persist,我应该能够打印从Cache.json加载的Default_OdbccDriver的缓存值。但我得到的却是:

>>>Config.Default_OdbccDriver
>>>''
很明显,Main正在导入Config.py,因为否则调用property.Default\u OdbccDriver时会出错。然而,尽管Default_OdbccDriver的值应该是“全局的”(根据python对这个词的奇怪定义),但它的值应该是静态的,并且在导入缓存中保持不变


有人知道发生了什么或者如何解决吗?最后,我希望main()初始化一些值并公开一些使用我的应用程序的方法,但这不是一个好的开始…

您应该在
init
函数中将变量声明为
global
,否则您只需设置函数的一些局部变量来隐藏全局变量:

def init():
    """docstring"""
    global Default_MSSQLPassword
    global Default_MSSQLUser
    global Default_OdbccDriver
    global MDGSQLP01

    with open("Cache.json", "r") as f:
        dtGlobalConstants = json.load(f)

    Default_MSSQLPassword = dtGlobalConstants["Default_MSSQLPassword"]
    Default_MSSQLUser = dtGlobalConstants["Default_MSSQLUser"]
    Default_OdbccDriver = dtGlobalConstants["Default_OdbccDriver"]
    MDGSQLP01 = dtGlobalConstants["MDGSQLP01"] 
正如您在评论中所说,当导入会话时,变量绑定到
Main.Config。您的_var_name
用于解决此问题,应该足以在模块中将其声明为全局变量:

#Config.py
import os
import json

global Default_MSSQLPassword
global Default_MSSQLUser
global Default_OdbccDriver
global MDGSQLP01

Default_MSSQLPassword = ""
Default_MSSQLUser = ""
Default_OdbccDriver = ""
MDGSQLP01 = ""


def init():
    """docstring"""
    global Default_MSSQLPassword
    global Default_MSSQLUser
    global Default_OdbccDriver
    ...

看起来您正在使用config,就像它是一个类一样,但没有将其定义为一个类。如果您想要一个配置对象,可以这样定义它:

#Config.py
import os
import json

class Config:

    def __init__(self):
        """docstring"""

    dtGlobalConstants = {}

    with open("Cache.json", "r") as f:
        dtGlobalConstants = json.load(f)

    Default_MSSQLPassword = dtGlobalConstants.get("Default_MSSQLPassword", "")
    Default_MSSQLUser = dtGlobalConstants.get("Default_MSSQLUser", "")
    Default_OdbccDriver = dtGlobalConstants.get("Default_OdbccDriver", "")
    MDGSQLP01 = dtGlobalConstants.get("MDGSQLP01", "")
现在,当您第一次实例化一个config对象时,比如
config=config()
,该
config
对象将包含所有这些变量

还要注意,如果在dict.get()函数中找不到变量,它会将变量设置为“”


如果改用类,则可以避免使用全局变量,甚至可以通过编写
get\u db\u object
函数来更新配置以从功能上返回数据库对象,这样您就可以使用config.get\u db\u object()创建数据库对象了

我得到了一些有趣的结果。奇怪地如果我使用:
from Main import Main
从交互式窗口调用函数并运行
Main()
我仍然会得到一个空字符串。但是,如果我从交互式窗口运行脚本,比如
exec(open(“Main.py”).read())
,那么配置变量的值将按预期返回。知道为什么会发生这种情况吗?@JamieMarshall是的,当导入到会话中时,变量并不是真正的全局变量,它们绑定到
Main.Config。你的_var_name
哇,真是个怪人!我甚至无法使用
从Main import Main
获取Main.Config.var,我不得不返回并
import Main
,这很奇怪,因为
Main
对象已经存在,并且具有变量的值。真奇怪。那么这真的是
import
exe
之间的访问不一致,还是实际上创建了两个单独的配置实例?@jamiemashall,在exe中,主作用域是主文件,在交互会话中是会话本身,这就是为什么它不能像spectedI那样工作我不相信这是正确的。我真正需要的是全局和静态的变量,但是Python对这两个概念的定义非常不传统。由于导入创建了目标模块的静态对象,因此它可能是最接近全局静态变量的对象。就我所阅读的python文档而言,我不能保证类中有一个静态值,因为它是在各种其他模块或包中导入的。我现在无法找到它,但我确信我直接从Python3.6文档中使用了这个方法。而且,根据定义,对象是非静态的。我想这取决于你将如何处理这些变量。如果要在其他模块中创建数据库连接对象,则不必将这些值保存为全局变量,可以创建这样的类,而只返回数据库对象。这些值将是“静态”的,因为它们永远不会被您的代码更改,特别是如果它们仅被此类用于创建DB对象,而您在python shell中尝试使用它们的方式可以更改,因此可以认为不是静态的,也只是我的拙见,我个人更喜欢我的代码中有更多的对象和类,我的意思是我可能在早期就错了。澄清一下,我指的是静态变量,它只有一个实例,在给定的时间内,无论从何处调用,都将包含相同的值。能够被改变是一件非常好的事情。
#Config.py
import os
import json

class Config:

    def __init__(self):
        """docstring"""

    dtGlobalConstants = {}

    with open("Cache.json", "r") as f:
        dtGlobalConstants = json.load(f)

    Default_MSSQLPassword = dtGlobalConstants.get("Default_MSSQLPassword", "")
    Default_MSSQLUser = dtGlobalConstants.get("Default_MSSQLUser", "")
    Default_OdbccDriver = dtGlobalConstants.get("Default_OdbccDriver", "")
    MDGSQLP01 = dtGlobalConstants.get("MDGSQLP01", "")