【问题标题】:python global variable scope confusion. What are these variables not accessible?python 全局变量范围混淆。这些变量是什么不可访问的?
【发布时间】:2016-11-07 17:31:16
【问题描述】:

我看到这里有一些这样的问题,但我还没有找到一个与我所追求的匹配的问题。

我有一个通用文件,我们称之为 tools.py。在这个文件中,我有许多要使用的路径定义和一个 init_paths 函数来根据命令行参数设置一些关键路径:

def init_paths(args):
    global tools_dir, tools_src, tools_bin

    if args.tools_set:
        tools_dir = os.path.realpath(os.path.join(args.tools_set,"tools"))
    else:
        tools_dir = os.path.join(BAR_PATH, "tools")

FOO_PATH = os.path.realpath(os.path.join(os.path.dirname(os.path.realpath(__file__)), ".."))
BAR_PATH = os.path.join(FOO_PATH, "foobar")
tools_dir = none
tools_src = none
tools_bin = none

等等……

我有一个主文件,我们将其命名为 main.py,我想在其中使用这些文件。

if __name__ == "__main__":
    args = parseArgs()
    from tools import init_paths
    init_paths(args)
    doStuffFunction(args.one, args.two, args.three)

为了确定,我已经省略了肉和土豆,但我相信这应该足以说明我的全球范围问题。当我运行这个:python main.py --tools-set=/path/to/tools 时,我期待调用 init_paths 来设置一些我希望稍后在doStuffFunction() 中使用的关键路径。

def doStuffFunction():
    searchPath = os.path.join(tools_dir, "folder")

这失败了:AttributeError: 'NoneType' object has no attribute endswith

很确定这是因为它没有被设置。但为什么呢?

编辑

main.py

#!/usr/bin/env python
import sys
import os
import argparse
import glob
from tools import *


def parseArgs():
    parser = argparse.ArgumentParser(description="parse my args")
    parser.add_argument("--toolchain-root", type=str,default=None,help='specify toolchain directory')
    args = parser.parse_args()

    return args


def doStuffFunction():
    output = 'output'
    if not os.path.isdir(output):
        os.makedirs(output)
    gimmySugar(output)

def gimmySugar(output):
    fileList = []
    linkBook= {}

    searchPath = os.path.join(tools_BIN_ROOT,'gcc-4.8.5')
    for root, dirs, files in os.walk(searchPath):
        for libFile in glob.glob(root+'/*.so*'):
            fileList.append(libFile)
            if os.path.islink(libFile):
                linksWith = os.readlink(libFile)
                linkBook[libFile] = linksWith

if __name__ == "__main__":
    # script was called directly from the command line
    args = parseArgs()
    from tools import init_settings
    init_settings(args)
    doStuffFunction()

tools.py

import os

def init_settings(args):
    global tools_DIR, tools_SRC_ROOT, tools_OBJ_ROOT, tools_BIN_ROOT
    if args.toolchain_root:
        tools_DIR = os.path.realpath(os.path.join(args.toolchain_root, "toolchain"))
    else:
        tools_DIR = os.path.join(USER_DIR, "")
    tools_SRC_ROOT = os.path.join(tools_DIR, "src")
    tools_OBJ_ROOT = os.path.join(tools_DIR, "obj")
    tools_BIN_ROOT = os.path.join(tools_DIR, "bin")


ROOT_PATH = os.path.realpath(os.path.join(os.path.dirname(os.path.realpath(__file__)), ".."))
OUTPUT_PATH = os.path.join(ROOT_PATH, "outputs")
BUILD_PATH = os.path.join(OUTPUT_PATH, "build")
USER_DIR = "/usr/lib64/"
tools_DIR = None
tools_SRC_ROOT = None
tools_OBJ_ROOT = None
tools_BIN_ROOT = None

【问题讨论】:

  • none 不是有效的 python,它是 None。分析不能 100% 反映您正在做什么的代码是没有用的。
  • “全局”变量在 Python 中确实是模块级的。 tools.init_pathstools 模块中设置全局变量,而不是导入它的模块。
  • 请将您的原始程序缩减为显示错误的最小可能完整程序。请edit您的问题并将整个短程序复制粘贴到您的问题中。请参阅minimal reproducible example 了解更多信息。
  • 感谢 cmets,我认为 user2357112 可能已经回答了我的问题,但我不确定是否有解决方案。我会将我的代码减少到一个小的可行并编辑它。稍等片刻。

标签: python global-scope


【解决方案1】:
#This line will failed
searchPath = os.path.join(tools_BIN_ROOT,'gcc-4.8.5')

全局变量的作用域是模块级别的,tools_BIN_ROOT不跨模块传递是不会被共享的。

变量tools_BIN_ROOT 是仅在tools.py 中的全局变量。相反,ma​​in.pytools.py 中不包含任何全局变量。

为了检查这个,您可以在两个文件中使用print(globals())


尽可能不要使用全局变量。

这是一个简单的解决方法。

(我强烈建议你通过 config 或 OOP 重构你的代码)

tools.py

def get_tools_BIN_ROOT():
    return tools_BIN_ROOT

os.py

from tools import get_tools_BIN_ROOT
searchPath = os.path.join(get_tools_BIN_ROOT(),'gcc-4.8.5')

【讨论】:

  • 感谢您提供简单的解决方案!我现在更好地理解 global 只是模块级的;再次感谢。
猜你喜欢
  • 2015-08-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-08-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多