简体   繁体   中英

Not able to access object in python while creating object of other class defined in some other file

I have a directory structure like this:

home/
    main.py

    lib/
       mylib/
            Textfile_Class.py
            Excelfile_Class.py
            globals.py   (has all the global variables declared here)
            functions.py

I created an object of Textfile_class in main.py using txt = TEXT(file) .

Now, I want to use this variable txt during creating object of Excelfile_Class for some operations (eg, if the value of a variable in txt object is 5, then do certain action in Excelfile_Class )

In Excelfile_Class , I am also importing all the global variables. String variables are accessible there but I dont know why this object txt is not accessible there. Wherever I am refering to txt in Excelfile_Class ( self.line_count = txt.count ), I am getting below error: AttributeError: 'NoneType' object has no attribute 'count'

Please help me to know why this is happening even though I have defined all the variables in a seperate file and importing those in all the files.

Eg: main.py

path = os.path.abspath('./lib')
sys.path.insert(0, path)

from mylib.Textfile_class import * 
from mylib.Excelfile_Class import *
from mylib.globals import *
from mylib.functions import *

if __name__ == "__main__":   
    txt = TEXT(file)
    xcel = EXCEL(file)

Eg globals.py

global txt, xcel
txt=None
xcel=None

Eg Textfile_class.py

from globals import *
class TEXT:
    def __init__(self, filename):
        self.count = 0
        with open(filename) as fp:
            for line in fp:
                self.count = self.count + 1`

Eg Excelfile_Class.py

from globals import *

class EXCEL:
    def __init__(self, filename):
        self.line_count = 0
        self.operation(filename)

    def operation(self, file):
        self.line_count = txt.count 
        if self.line_count:
            self.some_operation()
        else:
            self.other_operation()

When you assign a value to a variable name inside a function, you're not working with the global version of the variable any more, instead you have a completely new variable.

You have to use global keyword inside the function to indicate you're working with a global variable.

From Python Doc FAQ

What are the rules for local and global variables in Python?

In Python, variables that are only referenced inside a function are implicitly global. If a variable is assigned a new value anywhere within the function's body, it's assumed to be a local. If a variable is ever assigned a new value inside the function, the variable is implicitly local, and you need to explicitly declare it as 'global'.

Read more...

Example:

x = None                # x is momdule-level global variable

def local():
    x = 5               # assign 5 to x, here x is a new variable, global x is not affected.

def glob():
    global x            # indicate we'll working with the global x.
    x = 5               # this affect the global variable.

def print_global():
    print(x)            # Just print the global variable.

local()                 
print_global()          # Prints None
glob()
print_global()          # Prints 5

So, every time you refer to txt inside a function, you have to tell the context you'll be working with the global version of txt .

Other thing can be happening!

Python is interpreted, that means it execute the code line by line, if in the others modules (not in the main module) you have code trying to access txt before some value be assigned

if __name__ == "__main__":   
    txt = TEXT(file)

, then you'll get the same error.

A recommendation:

Try to avoid the use of global variables, you already know that isn't a good practice and it leads to unestable code.

If your problem is that you want to txt and xcel to be available at any time anywhere, you could use the pattern Singleton (warning, Singleton is considered an anti-pattern ref )

I will post an example for you, but before I will encorage you to redesign your program, I ensure you it will be a good exercise!

Singleton example: (again this is an anti-pattern, but I preffer it to nude global variables).

class Globals(object):

    __instance = None

    def __init__(self):

        class wrapped_class:
            def __init__(self):
                self.txt = None
                self.excel = None

        if (Globals.__instance is None):
            Globals.__instance = wrapped_class()

    def __getattr__(self, attrname):
        return getattr(self.__instance, attrname)

    def __setattr__(self, attrname, value):
        setattr(self.__instance, attrname, value)

glob = Globals()            # Since __instance is None this will instantiate wrapped_class and save the reference in __instance
glob.txt = "Txt example"    # Modify the txt attribute of __instance. 
glob_1 = Globals()          # Since __instance is not None it stays as it is.

print(glob.txt)             # Prints  "Txt example"
print(glob_1.txt)           # Prints  "Txt example"

It is quite hard to tell where your problem is without having the code or the stack trace but I would strongly advice that you read some documentation about Python best practices, the use of global variables and naming conventions. This by itself might solve your issues. Naming conventions might sound silly but those things and other syntax-related choices do matter in python.

Also, you seem to be missing __init__.py file in your module which may or may not be important depending of the python version you are using.

Here are a few links to get you started:

I dont know why it happened like that. If anyone knows they can tell.

The problem got resolved when I used the method given in Using global variables between files in Python .

So, finally I put all the global variables in a function in globals.py and instantiated that once in main.py . Then, I used from mylib import globals and referenced the global variables inside the classes as globals.txt and it worked fine.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM