How to pass global variables between files in python - python

I have a semi-large python app that runs on linux. I am trying to set it up so that i can read a config file at program startup and then save those values for use at any time while the application is running, without re-reading the config file.
So I am trying to load a configValues class in my first modual, test.py. And read the values set. Then in this example read the values again in test2.py.
I never get the values. Can someone help me?
Config.py
class config():
def __init__(self):
configFile = File(myPath)
if configFile.exist():
myXML = str(configFile.openAndRead())
def setupValues(self):
configValues.color = self.getElement('color')
def getElement(self, element):
tree=et.fromstring(self.myXML)
for el in tree.findall('head'):
for ch in el.findall(element):
return ch.text
class configValues():
def __init__(self):
global color
test.py
import config
class test():
def __init__(self):
configObj = config.Config()
configVal = config.configValues()
configObj.setupValues()
print configVal.color
test2.py
import config
class test2():
def __init__(self):
configVal = config.configValues()
print configVal.color

Add a global variable and a function to your config.py. And rather than creating configobj in test1.py and test2.py, you can call this function to get the config object.
configobj = None
def getconfigobj():
global configobj
if not configobj:
configObj = config.Config()
return configobj
Edit as per comment. Does something like the following help(using a single instance for the class)?:-
config.py
class config():
_instance = None
def __new__(cls):
if config._instance:
return config._instance
return super(config, cls).__new__(cls)
def __init__(self, myPath):
configFile = File(myPath)
if configFile.exist():
myXML = str(configFile.openAndRead())
config._dict['instance'] = self
def setupValues(self):
self.color = self.getElement('color')
def getElement(self, element):
tree=et.fromstring(self.myXML)
for el in tree.findall('head'):
for ch in el.findall(element):
return ch.text
test1.py
import config
class test():
def __init__(self):
configObj = config.Config()
configObj.setupValues()
print configObj.color
test2.py
import config
class test2():
def __init__(self):
configObj = config.Config()
print configObj.color

I would not use global variables in this case. You may want to assign the config values as config properties and use it like so:
config.py
class Config:
def __init__(self):
# property of the config class
self.color = 'my default color'
# open your config file ..
def setup_values(self):
# assign new value
self.color = self.get_color()
def get_color(self):
# get values from config xml file ..
return "red"
And then import the config in other module and call the color property:
main.py
from config import Config
class Main:
def __init__(self):
config = Config()
config.setup_values()
color = config.color
print color
Main()
I would also shorten the code with one method less by getting the config values in the constructor instead in additional method "setup_values" like so:
class Config:
def __init__(self):
# property of the config class
self.color = self.get_color()
def get_color(self):
# open your config file ..
# get values from config xml file ..
return "red"
and the main.py should look like:
from config import Config
class Main:
def __init__(self):
config = Config()
color = config.color
print color
Main()
Bear in mind that it is not a good practice to use global variables in your code so the suggested code above may do the job for you.

Related

How to dynamically import the class?

I have four files: main.py, MainClass.py, SigClass.py, and MyClassC.py. The entry is main.py. I rewrite the function function_a of MyClassA in MyClassC, so I need to set SigClass in main.py sig attribute, so MainClass inherits MyclassC and MyclassA in MainClass.py. My code is as follows, which does not inherit the function function_a of MyClassC.
This question explains why the weird class in the middle is used.
I have tried many methods, but I can only achieve my goal in TempClass in the main() space of MainClass.py, but in __main__ of MainClass.py Space can't do it.
How can the TempClass in the main() space be referenced in other files? I really can’t think of a way.
How can I modify the code? Or is there any other way?
The sample code is as follows:
main.py:
from MainClass import SigClass, main
SigClass.sig = "MyClassC"
main()
from MainClass import MainClass
MainClass.function_a()
print(MainClass.property)
MainClass.py:
from time import time
from SigClass import SigClass
import importlib
sig = SigClass.sig
class MyClassA:
sig = '1'
property = 'A'
#classmethod
def function_a(cls):
cls.property = 'A'
class MainClass:
pass
def main():
module_name = SigClass.sig
class_name = SigClass.sig
module_object = importlib.import_module(module_name)
module_class_object = getattr(module_object, class_name)
class TempClass(module_class_object, MyClassA):
pass
global MainClass
MainClass = TempClass
SigClass.py
class SigClass:
sig = 1
MyClassC.py
from MainClass import MyClassA
class MyClassC(MyClassA):
#classmethod
def function_a(cls):
cls.property = 'c'
pass
Thanks to #2e0byo's tips, I think the following code best meets my needs:
Import MyClassC according to SigClass.sig, and SigClass.sig is also the most important part of MainClass.
class BaseClass:
name = None
pass
class SigClass(BaseClass):
name = "SigClass"
sig = 1
class MyClassA(BaseClass):
name = "MyClassA"
property = 'A'
sig = 'a'
#classmethod
def function_a(cls):
pass
class MyClassC(MyClassA):
name = "MyClassC"
property = "C"
sig = 'c'
#classmethod
def function_a(cls):
pass
class ClassCollections(BaseClass):
classes: dict = {}
#classmethod
def add_class(cls, class_to_add: type(BaseClass)):
cls.classes[class_to_add.name] = class_to_add
SigClass.sig = "MyClassC"
ClassCollections.add_class(MyClassA)
ClassCollections.add_class(MyClassC)
class MainClass(SigClass, ClassCollections.classes[SigClass.sig], MyClassA):
pass
print(MainClass.sig)
MyClassC

How to reference function defined in __init__ super class

I have a helper function (def convert(dictionary) inside my __init__ class to assist with configuration setup. The definition is as follows:
class Configuration:
def __init__(self, config_file=None, config=None):
if config_file is not None:
with open(config_file) as in_file:
self._config = yaml.load(in_file, Loader=yaml.FullLoader)
elif config is not None:
self._config = config
else:
raise ValueError("Could not create configuration. Must pass either location of config file or valid "
"config.")
def convert(dictionary):
return namedtuple('Config', dictionary.keys())(**dictionary)
This allows me to make a call within __init__ as follows:
self.input = convert(self._config["input"])
self.output = convert(self._config["output"])
self.build = convert(self._config["build_catalog"])
Since I have more than one configs to set up I want to inherit from his class as follows:
class BuildConfiguration(Configuration):
def __init__(self, config_file=None, config=None):
super().__init__(config_file, config)
self.input = convert(self._config["input"])
self.output = convert(self._config["output"])
self.build = convert(self._config["build_catalog"])
I however do not gain access to convert from the parent class. I have also tried this:
self.input = super().__init__.convert(self._config["input"])
This also seems to not work.
So the question is how do I get access to a function defined in super().__init__ from child classes?
You can't. A new function is created on each invocation of __init__ and it is discarded, it doesn't exist outside the function. Note, this also applies to the class being created by namedtuple('Config', dictionary.keys())(**dictionary). It really isn't good to keep creating all these unnecessary classes, which totally defeats the purpose of namedtuple which is for creating memory-efficient record-types. Here, each instance has it's own class!
Here is how you should define this:
Config = namedtuple('Config', "foo bar baz")
def convert(dictionary): # is this really necessary?
return Config(**dictionary)
class Configuration:
def __init__(self, config_file=None, config=None):
if config_file is not None:
with open(config_file) as in_file:
self._config = yaml.load(in_file, Loader=yaml.FullLoader)
elif config is not None:
self._config = config
else:
raise ValueError("Could not create configuration. Must pass either location of config file or valid "
"config.")
self.input = convert(self._config["input"])
self.output = convert(self._config["output"])
self.build = convert(self._config["build_catalog"])
Although at this point, it seems cleaner to just use
Config(**self._config["input"])
etc instead and ditch the helper convert.

Python namespace and global variable between files

I have 2 differents files. The first one, defines a lot of class:
# File 1:
class Class1:
class Class2:
#...
Those classes uses some variables that are define as global.
# File 1:
class Class1:
def __init__(self, var1):
global glob_variable_1
# Other stuff
class Class2:
#...
In the file 2, I import all the class from the first file and then use them. In this main part of this file, I define the global variables.
# File 2
from File1 import Class1, Class2
if __name__ == '__main__':
global glob_variable_1
glob_variable_1 = 10
# Other stuff
Class1(var1)
I get the error NameError: name 'glob_variable_1' is not defined.. I suppose
it's a problem of namespace and scope, but I don't really understand how it works. Can someone give me a hand? Thanks.
You have two glob_variable_1 names, one in each namespace and you must decide which one to use:
# File 1:
# defined here, outside the class
glob_variable_1 = None
class Class1:
def __init__(self, var1):
global glob_variable_1
glob_variable_1 = 42
# Other stuff
class Class2:
pass
with:
# File 2
from File1 import Class1, Class2
import File1
if __name__ == '__main__':
global glob_variable_1
# Other stuff
var1 = 1234
obj = Class1(var1)
glob_variable_1 = 666
print(glob_variable_1)
print(File1.glob_variable_1)
Gives:
666
42
Far better than using a global variable across modules is to use a function to set/get in a class or a file.

confused value scope in python

Hi I have staring programming with c and I conld'nt understand value scope in python.
here is my code
class ScenarioEnvironment():
def __init__(self):
print(self)
class report():
config = ScenarioEnvironment()
def __init__(self):
self.config = ScenarioEnvironment()
what happens passing config and config at init()?
and I wonder the value scope which config will be class valuable?
You need to know the differences between class attribute and instance object attribute.
Maybe these codes will help you:
class TestConfig1(object):
config = 1
def __init__(self):
self.config = 2
class TestConfig2(object):
config = 1
def __init__(self):
self.config2 = 2
if __name__ == "__main__":
print TestConfig1.config
t = TestConfig1()
print t.config
t2 = TestConfig2()
print t2.config
print t2.config2
more you can see the python blog.click here
Since your question seems a bit ambiguous, I'll just comment/fix your code:
class ScenarioEnvironment():
def __init__(self,x):
self.x = x # Assigning instance variable x to constructor parameter x.
print(self) # You're printing the object instance.
class report():
# Static variable shared amongst all classes.
config = ScenarioEnvironment(None) # Assigned to new instance of ScenarioEnvironment.
def __init__(self):
# No argument, must pass one (None).
# self.config is to a new ScenarioEnvironment instance.
self.config = ScenarioEnvironment(None)
Lets try out the classes.
Output:
s = ScenarioEnvironment(None)
r = report()
>>> <__main__.ScenarioEnvironment instance at 0x026F4238>
>>> <__main__.ScenarioEnvironment instance at 0x026F4300>
>>> <__main__.ScenarioEnvironment instance at 0x026F4350>

Python namespace confusion and how to re-use class variables

i have following issue with the below python code:
templates.py
class globalSettings:
def __init__(self):
self.tx_wait = 1200
self.tx_Interval = 30
general.py
from templates import *
class testSuit(object):
def __init__(self):
testSuit.settings = globalSettings()
def readMeasurements(self, filename, revision, lsv):
testSuit.settings.tx_wait = 100
testSuit.settings.tx_Interval = 25
test.py
import general
from templates import *
class testcase(object):
def __init__(self):
self.settings = general.testSuit.settings
But this gives me:
self.settings = general_main.testSuit.settings
AttributeError: type object 'testSuit' has no attribute 'settings'
The several imports that i do are needed for the rest of the code!
What i want to achieve is to be able to load different settings for the globalSettings class but have default values.
So, the def readMeasurements is actually reading new values if found from an excel sheet. This part is working fine!
What am i doing wrong in my coding?
Thanks for your time!
Assuming you want the variables to be instance specific:
class testSuit(object):
def __init__(self):
testSuit.settings = globalSettings()
def readMeasurements(self, filename, revision, lsv):
testSuit.settings.tx_wait = 100
testSuit.settings.tx_Interval = 25
Should be:
class testSuit(object):
def __init__(self):
self.settings = globalSettings()
def readMeasurements(self, filename, revision, lsv):
self.settings.tx_wait = 100
self.settings.tx_Interval = 25
Assuming you want the variables to be static instead of instance defined, you should be able to use the following:
class testSuit(object):
settings = globalSettings()
def readMeasurements(self, filename, revision, lsv):
settings.tx_wait = 100
settings.tx_Interval = 25
You can declare settings = globalSettings() outside of the init function (which isn't needed here).
With your current code you may be able to access the variables by using:
self.settings = general.testSuit.testSuit.settings

Categories

Resources