Set a variable from a class within a different file - python-3.x

I have 2 files:
fileA.py
and
fileB.py
I am trying to set (change) a variable from fileA from a function within fileB. The variable I'm trying to change is inside of a class (I believe the variable is a Class variable). I tried importing fileA inside of fileB but got errors.
# fileA:
...
class SomeDialog(QDialog):
my_var = 0
...
# fileB:
...
from fileA import SomeDialog as sd
def my_func():
sd.my_var = 5
...
Any help?

According to the error you got, you probably have circular import somewhere. It is not related to what you are trying to do with your classes.
See ImportError: Cannot import name X for more details
If that's the case, the only way to solve it is to change your file structures.

Your class should look like this:
class SomeDialog(QDialog):
def __init__(self):
self.my_var = 0
Then you can access the my_var like this:
SomeDialog.my_var

Class variables are defined within a class but outside any of the class's methods. Class variables are not used. class variables have the same value across all class instances
A.py
from B import SomeDialog as sd
def my_func():
print sd.my_var
sd.my_var = 5
return sd
_my_func = my_func()
print _my_func.my_var
B.py
class SomeDialog(object):
my_var = 0
#output
0
5

Related

Python create dynamic class and set multi bases from imported module

I found several example here, but is not what exactly looking for, will try to explain here
from this answer tried to achieve my result but is not what looking for
How can I dynamically create derived classes from a base class
i have a module that holds many classes
importing the module
import importlib
# are awalable many classes here
forms = importlib.import_module('my_forms')
Now, based on forms i need to create a new class and add bases to my new class all classes that are availabe in forms
this what i tried, but can not find a way to assign the bases
import inspect
def create_DynamicClass():
class DynamicClass(BaseClass):
pass
for form_name, class_name in inspect.getmembers(forms):
for i in class_name():
# here the code to added all bases to DynamicClass
return DynamicClass()
example how my_forms module looks
class MyClass1(BaseClass):
attr1 = 1
attr2 = 2
#coroutine
def prepare(self):
# some code for each class
class MyClass2(BaseClass):
attr3 = 3
attr4 = 4
#coroutine
def prepare(self):
# some code for each class
class MyClass3(BaseClass):
attr5 = 5
attr6 = 6
#coroutine
def prepare(self):
# some code for each class
The result that i want to achieve is the following, will make a static class to show desired result but need to be dynamic
I need to create my class dynamic because in my_forms module can be any amount of classes
# inherits all classes from my_forms module
class MyResultClass(MyClass1, MyClass2, MyClass3):
# here get all available attributes from all classes
#coroutine
def prepare(self):
# as well need each prepare function for each class as well
yield MyClass1().prepare()
yield MyClass2().prepare()
yield MyClass3().prepare()
Simply declare the dynamic class with all of your base classes. To do so, put all of your base classes in a list, and unpack the list in the class definition statement with the * operator like this:
def createClass(baseClasess):
class NewClass(*baseClasses):
pass
return NewClass
DynamicClass = createClass([class1, class2, ...])
i have managed to find a solution, will post here, if any recommendation to make it better will appreciate
forms = importlib.import_module('my_forms')
class Form(BaseForm):
#coroutine
def prepare(self):
for form_name, class_name in inspect.getmembers(forms, inspect.isclass):
try:
yield class_name().prepare()
except TypeError:
continue
def createClass(meta):
for form_name, class_name in inspect.getmembers(forms, inspect.isclass):
try:
Form.__bases__ += (class_name, )
for field in class_name():
field_type = fl.SelectField() if hasattr(field, 'choices') else fl.StringField()
setattr(Form, field.name, field_type)
except TypeError:
continue
return Form(meta=meta)

Python Inner Class Inheritence

I'm trying to define my config.py using class in Python, such that, every class will have some "static" members, that will be read for my configuration settings. I'm using inner classes and using inheritence among them.
Here is an example of what I'm trying to do:
class Prod:
class default_configs:
var1 = "pppp"
var2 = var1 + "D"
class mode1(default_configs):
var2 = default_configs.var1 + "M1"
class mode2(default_configs):
var2 = "M2"
...
...
class Local:
pass
I'm getting the error when I'm setting var2 in class mode1. It says:
"default_configs is not defined"
as if, it is treating default_configs as a member-variable. So, what am I doing wrong and how can I get this to work? Also, mode2.var1 and mode2.var2 have values as expected.
I tried using parent reference as well, like Prod.default_configs.var1 but that did not work either. I also tried accessing var1 directly, as if inherited, it should be usable, but I was wrong again.
I think you're overworking your solution a bit. Inheritance and static variables and methods can be handled quite easily in Python.
Given your example above, let's say we have a Config class, which has a couple of static attributes and methods, and you want to create both Local and Prod classses which both inherit from a base class Config:
class Config:
var1 = "pppp" # These two are class variables now
var2 = var1 + "D"
def __init__(self):
self.var3 = 'Local variable'
self.var4 = None # We define it here so it doesn't throw an exception afterwards
#staticfunction
def mode1(cls):
"""
Here we use the cls variable to reference the class, as we would
do with self in an instance method
"""
cls.var2 = cls.var1 + "M1"
def instance_function(self):
self.val4 = 'Instance variable'
class Prod(Config):
def mode2(self):
print(self.var2) # ppppD
super().var2 = "M2" # The parent class in subclasses is defined by super()
self.var2 = "M3" # super().var2 and self.var2 will have different values
print(super().var2) # M2
super().model()
print(super().var2) # M1
print(super().var3) # Throws Exception: Variable not found
print(self.var3) # Local variable
print(self.var4) # None
self.instance_method()
print(self.var4) # Instance variable
class Local(Config):
def __init__(self):
"""
This runs the superclass constructor. It's run by default on single-class
inheritance, but let's run it anyway just for the sake of it.
"""
super().__init()__
def mode2(self):
print(super().var2) # ppppD
super().var2 = "M2" # The parent class in subclasses is defined by super()
print(super().var2) # M2
print(self.var2) # M3

How to import variable values from a file that is running?

I am running a python file, say file1, and in that, I am importing another python file, say file2, and calling one of its functions. Now, the file2 needs the value of a variable which is defined in file 1. Also, before importing file2 in file1, the value of the variable was changed during the run-time. How do I make the file file2, access the current value of the variable from file 1?
The content of file1 is:
variable = None
if __name__ == '__main__':
variable = 123
from file2 import func1
func1()
The content of file2 is:
from file1 import variable as var
def func1():
print(var)
When I run the file1, I want the function func1 in file2 to print 123. But it prints None. One way I can tackle this is by saving the content of the variable in some ordinary file when it is modified, and then retrieving it when needed. But the application in which I am using this code, the size of the variable is massive, like around 300 MB. So, I believe it won't be efficient enough to write the content of the variable in a text file, every time it is modified. How do I do this? (Any suggestions are welcome)
The main script is run with the name __main__, not by its module name. This is also how the if __name__ == '__main__' check works. Importing it by its regular name creates a separate module with the regular content.
If you want to access its attributes, import it as __main__:
from __main__ import variable as var
def func1():
print(var)
Note that importing __main__ is fragile. On top of duplicating the module, you may end up importing a different module if your program structure changes. If you want to exchange global data, use well-defined module names:
# constants.py
variable = None
# file1.py
if __name__ == '__main__':
import constants
constants.variable = 123
from file2 import func1
func1()
# file2.py
from constants import variable as var
def func1():
print(var)
Mandatory disclaimer: Ideally, functions do not rely on global variables. Use parameters for passing variables into functions:
# constants.py
variable = None
# file1.py
if __name__ == '__main__':
from file2 import func1
func1(123)
# file2.py
from constants import variable
def func1(var=variable):
print(var)

How to access an object created in one file in another class from anohter file?

I am creating a quick numerical solver where all variables are shared among different files. Thus the Object containing the variables must be accessed by all files in the project.
This is a numerical application which solves the Laplace Equation. Unfortunately, my experience is basically on Fortran90 and MPI and nothing on OOP. I want to keep each "subroutine" isolated on each file. This is how I have developed codes with thousands of lines in CFD but in Fortran using procedural. I'd like to use the same idea but with objects.
file1.py
class Variables:
def __init__():
self.AnodeLength = 2.0
self.CathodeLength = 1.0
self.Length = 0.0
......
# a bunch of more variables
file2.py
from file1 import *
ME = Variables()
# ME is the object from the class Variables from file1.py and it contains all the variables needed for the computation.
GridSolver = Grid()
GridSolver.GridGeneration #Here is the problem
file3.py
from file2 import *
class Grid:
def GridGeneration(self):
EM.Length = EM.AnodeLength + EM.CathodeLength
When I execute the previous code it gives me the error of EM is not recognized. I guess it makes sense because the EM is not in the scope of that class but in file2.py where I initiated.
Is there any option to pass an Object to a class as an argument? For example, If I could pass the object EM into the class Grid I could pull the attributes from that object inside the Grid Class and I think I could solve my problem.
Is it possible to make an object global such that every class (From every file) on the same directory can access that object?
Based on your current approach, yes you can pass an Object to a class as an argument. Your updated code will look like
file1.py
class Variables:
def __init__():
self.AnodeLength = 2.0
self.CathodeLength = 1.0
self.Length = 0.0
......
# a bunch of more variables
file2.py
from file1 import *
ME = Variables()
# ME is the object from the class Variables from file1.py and it contains all the variables needed for the computation.
GridSolver = Grid()
GridSolver.GridGeneration(ME) #Passing the object as parameter
file3.py
from file2 import *
class Grid:
def GridGeneration(self, EM):
EM.Length = EM.AnodeLength + EM.CathodeLength
As you can see we have changed the GridGeneraion to accept an additional parameter.
Now let me show you the way all standard modules use constants.
file1.py
ANODE_LENGTH = 2.0
CATHODE_LENGTH = 1.0
LENGTH = 0.0
# a bunch of more variables
file2.py
GridSolver = Grid()
GridSolver.GridGeneration() # no need to pass parameter
file3.py
import file1
class Grid:
def GridGeneration(self):
EM.Length = file1.ANODE_LENGTH + file1.CATHODE_LENGTH
There is any issue with the above code, anyone can assign values to these constants. So in python, there is no constant. It means anyone can change values like this ANODE_LENGTH=100. Although, you can implement the constant implementation based on this post
so your file2.py implementation will change as below
class _file2:
class ConstError(TypeError): pass
def __setattr__(self,name,value):
if self.__dict__.has_key(name):
raise self.ConstError, "Can't rebind const(%s)"%name
self.__dict__[name]=value
import sys
sys.modules[__name__]=_file2()

Refer sqlContext as global variable [duplicate]

So I have two different files somewhat like this:
file1.py
from file2 import *
foo = "bar"
test = SomeClass()
file2.py
class SomeClass :
def __init__ (self):
global foo
print foo
However I cannot seem to get file2 to recognize variables from file1 even though its imported into file1 already. It would be extremely helpful if this is possible in some way.
Importing file2 in file1.py makes the global (i.e., module level) names bound in file2 available to following code in file1 -- the only such name is SomeClass. It does not do the reverse: names defined in file1 are not made available to code in file2 when file1 imports file2. This would be the case even if you imported the right way (import file2, as #nate correctly recommends) rather than in the horrible, horrible way you're doing it (if everybody under the Sun forgot the very existence of the construct from ... import *, life would be so much better for everybody).
Apparently you want to make global names defined in file1 available to code in file2 and vice versa. This is known as a "cyclical dependency" and is a terrible idea (in Python, or anywhere else for that matter).
So, rather than showing you the incredibly fragile, often unmaintainable hacks to achieve (some semblance of) a cyclical dependency in Python, I'd much rather discuss the many excellent way in which you can avoid such terrible structure.
For example, you could put global names that need to be available to both modules in a third module (e.g. file3.py, to continue your naming streak;-) and import that third module into each of the other two (import file3 in both file1 and file2, and then use file3.foo etc, that is, qualified names, for the purpose of accessing or setting those global names from either or both of the other modules, not barenames).
Of course, more and more specific help could be offered if you clarified (by editing your Q) exactly why you think you need a cyclical dependency (just one easy prediction: no matter what makes you think you need a cyclical dependency, you're wrong;-).
When you write
from file2 import *
it actually copies the names defined in file2 into the namespace of file1. So if you reassign those names in file1, by writing
foo = "bar"
for example, it will only make that change in file1, not file2. Note that if you were to change an attribute of foo, say by doing
foo.blah = "bar"
then that change would be reflected in file2, because you are modifying the existing object referred to by the name foo, not replacing it with a new object.
You can get the effect you want by doing this in file1.py:
import file2
file2.foo = "bar"
test = SomeClass()
(note that you should delete from foo import *) although I would suggest thinking carefully about whether you really need to do this. It's not very common that changing one module's variables from within another module is really justified.
from file2 import * is making copies. You want to do this:
import file2
print file2.foo
print file2.SomeClass()
global is a bit of a misnomer in Python, module_namespace would be more descriptive.
The fully qualified name of foo is file1.foo and the global statement is best shunned as there are usually better ways to accomplish what you want to do. (I can't tell what you want to do from your toy example.)
After searching, I got this clue: https://instructobit.com/tutorial/108/How-to-share-global-variables-between-files-in-Python
the key is: turn on the function to call the variabel that set to global if a function activated.
then import the variabel again from that file.
i give you the hard example so you can understood:
file chromy.py
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
def opennormal():
global driver
options = Options()
driver = webdriver.Chrome(chrome_options=options)
def gotourl(str):
url = str
driver.get(url)
file tester.py
from chromy import * #this command call all function in chromy.py, but the 'driver' variable in opennormal function is not exists yet. run: dir() to check what you call.
opennormal() #this command activate the driver variable to global, but remember, at the first import you not import it
#then do this, this is the key to solve:
from chromy import driver #run dir() to check what you call and compare with the first dir() result.
#because you already re-import the global that you need, you can use it now
url = 'https://www.google.com'
gotourl(url)
That's the way you call the global variable that you set in a function. cheers
don't forget to give credit
while I do the test following the idea of #robertspierre to put all global variables in a glv.py file and then import it in other files where it is used, the demo codes is given bellow, hope it helps:
the global variable file, glv.py:
# glv.py
glvB = True
glvA = 100
glvS = "tiger"
glvList = [1, 2, 3]
glvTuple = (1, "a")
glvDict = {"Name": "tiger", "age": 100}
sub1.py, it's a file that will import the glv.py file. Two functions are defined to show and change the global variable data in glv.py, showData() and changeData(),
# sub1.py
import glv
def showData():
print(f"*****glv in sub1*****\n"
f"glvB={glv.glvB}\n"
f"glvA={glv.glvA}\n"
f"glvS={glv.glvS}\n"
f"glvList={glv.glvList}\n"
f"glvTuple={glv.glvTuple}\n"
f"glvDict={glv.glvDict}\n")
def changeData():
glv.glvB = False
glv.glvA = 200
glv.glvS = "bactone"
glv.glvList = [4, 5, 6]
glv.glvTuple = (2, "b")
glv.glvDict = {"Name": "bactone", "age": 0}
sub2.py is another file:
# sub2.py
import glv
def showData():
print(f"*****glv in sub2*****\n"
f"glvB={glv.glvB}\n"
f"glvA={glv.glvA}\n"
f"glvS={glv.glvS}\n"
f"glvList={glv.glvList}\n"
f"glvTuple={glv.glvTuple}\n"
f"glvDict={glv.glvDict}\n")
def changeData():
glv.glvB = True
glv.glvA = 300
glv.glvS = "bactone"
glv.glvList = [7, 8, 9]
glv.glvTuple = (3, "c")
glv.glvDict = {"Name": "bactone1", "age": 10}
finally we test the global variable in main.py:
import glv
import sub1
import sub2
def showData():
print(f"*****initial global variable values*****\n"
f"glvB={glv.glvB}\n"
f"glvA={glv.glvA}\n"
f"glvS={glv.glvS}\n"
f"glvList={glv.glvList}\n"
f"glvTuple={glv.glvTuple}\n"
f"glvDict={glv.glvDict}\n")
if __name__ == "__main__":
showData() # show initial global variable
sub1.showData() # show global variable in sub1
sub1.changeData() # change global variable in sub1
sub2.showData() # show global variable in sub2
sub2.changeData() # change global variable in sub2
sub1.showData() # show global variable in sub1 again
the results turns out to be:
*****initial global variable values*****
glvB=True
glvA=100
glvS=tiger
glvList=[1, 2, 3]
glvTuple=(1, 'a')
glvDict={'Name': 'tiger', 'age': 100}
*****glv in sub1*****
glvB=True
glvA=100
glvS=tiger
glvList=[1, 2, 3]
glvTuple=(1, 'a')
glvDict={'Name': 'tiger', 'age': 100}
*****glv in sub2*****
glvB=False
glvA=200
glvS=bactone
glvList=[4, 5, 6]
glvTuple=(2, 'b')
glvDict={'Name': 'bactone', 'age': 0}
*****glv in sub1*****
glvB=True
glvA=300
glvS=bactone
glvList=[7, 8, 9]
glvTuple=(3, 'c')
glvDict={'Name': 'bactone1', 'age': 10}
we can see all kinds of data type works and the change of global variable is automatically reloaded.
I came to the conclusion that you can import globals, but you can not change them once imported. The only exception is if you pass them as arguments. I would love to be wrong on this, so let me know if there is a way to effectively re import updated globals. The two codes below will run.
from b import * # import all from b.py
global alpha # declare globals
global bravo
global charlie
alpha = 10 # assign values to globals
bravo = 20
charlie = 15
def run_one():
one(alpha) # pass the global to b.py
def run_two():
two() # rely on import statement in b.py
def run_three():
global charlie # declare the global to change it
charlie = 40 # change the value for charlie
print("charlie:", charlie, " --> global value changed in a.py run_three()")
def run_three_again(): # print charlie again from b.py
three()
def run_four(): # re import charlie in b.py
four()
if __name__ == "__main__": # prevent the code from being executed when b.py imports a.py
run_one() # run through all the functions in a.py
run_two()
run_three()
run_three_again()
run_four()
Also:
from a import * # import all from a.py
def one(alpha):
print("alpha: ", alpha, " --> global passed as argument in one()")
def two():
print("bravo: ", bravo, " --> global imported from a.py in two()")
def three():
print("charlie:", charlie, " --> global imported from a.py in three() but is not changed")
def four():
from a import charlie # re import charlie from a.py
print("charlie:", charlie, " --> global re-imported in four() but does not change")
The output from the print statements are below:
alpha: 10 --> global passed as argument in one()
bravo: 20 --> global imported from a.py in two()
charlie: 40 --> global value changed in a.py run_three()
charlie: 15 --> global imported from a.py in three() but is not changed
charlie: 15 --> global re-imported in four() but does not change
All given answers are wrong. It is impossible to globalise a variable inside a function in a separate file.
Just put your globals in the file you are importing.

Resources