0

I see there are a few of these questions on here, but I haven't found one that quit matches what I'm after.

I have a common file, lets call it tools.py. In this file I have a host of path definitions to use and an init_paths function to set some key paths based on command line arguments:

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

etc...

I have a main file, lets call it main.py where I want to use these.

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

I have left out the meat and potatoes to be sure, but I believe this should be enough to illustrate my global scope problem. when I run this: python main.py --tools-set=/path/to/tools, I am expecting the call to init_paths, to set up some key paths I wish to use later in the doStuffFunction().

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

this fails: AttributeError: 'NoneType' object has no attribute endswith

pretty sure this is because it is not getting set. but why?

EDIT

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
Jared Sanchez
  • 67
  • 1
  • 10
  • `none` is not valid python, it's `None`. It's no use analyzing code that doesn't 100% reflect what you're doing. – Marcus Müller Nov 07 '16 at 17:33
  • "Global" variables are really module-level in Python. `tools.init_paths` is setting globals in the `tools` module, not the module that imports it. – user2357112 Nov 07 '16 at 17:35
  • Please reduce your original program to the smallest possible **complete** program that demonstrates the error. Please [edit] your question and copy-paste that entire short program into your question. See [mcve] for more information. – Robᵩ Nov 07 '16 at 17:42
  • Thank you for the comments, I'm thinking that user2357112 might have answered my question, but I'm not sure yet on a solution. I will reduce my code to a small workable and EDIT this. hold on for a bit. – Jared Sanchez Nov 07 '16 at 17:54

1 Answers1

1
#This line will failed
searchPath = os.path.join(tools_BIN_ROOT,'gcc-4.8.5')

The scope of global variables is module level, tools_BIN_ROOT will not be shared without passing across modules.

The variable tools_BIN_ROOT is global variable ONLY in tools.py. Insteadly, main.py do not contain any global variable in tools.py.

For inspecting this, you can use print(globals()) in both files.


Do not use global variable if possible.

This is a simple workaround.

(I strongly recommend you to refactor your code by config or 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')
Kir Chou
  • 2,980
  • 1
  • 36
  • 48