Easiest way to share variables among files in Python? - python

I have a project with many Python files. There are certain number of variables in some files which I like to use in other files. For example, if
var=10
is defined in f1.py, what are the ways I can call/use "var" in other files without using from f1 import var ?
I tried using global but it doesn't work across all the files.
Thank you!

Declare all of your global variables in one file i.e. my_settings.py and then import that in your other scripts.
See this question and it's accepted answer for details:
Using global variables between files in Python

You could do it with namescope:
import f1
print(f1.var)
10
f1.var = 20
Then it should change var in all files which are using that variable with import.

Most of the times I encounter this problem I use different methods:
I put all constants that are to be used in all programs in a separate program that can be imported.
I create a "shared variables object" for variables that are to be used in several modules. This object is passed to the constructor of a class. The variables can then be accessed (and modified) in the class that is using them.
So when the program starts this class is instantiated and after that passed to the different modules. This also makes it flexible in that when you add an extra field to the class, no parameters need to be changed.
class session_info:
def __init__(self, shared_field1=None, shared_field2=None ....):
self.shared_field1 = shared_field1
self.shared_field2 = shared_field2
def function1(session):
session.shared_field1 = 'stilton'
def function2(session):
print('%s is very runny sir' % session.shared_field1)
session = session_info()
function1(session)
function2(session)
Should print:
"stilton is very runny sir"

Related

How Can I Make Python .py Files Share Variables & Constants?

I've been learning about about C++ in college and one thing that interests me is the ability to create a shared header file so that all the cpp files can access the objects within. I was wondering if there is some way to do the same thing in python with variables and constants? I only know how to import and use the functions or classes in other py files.
First, if you've ever used sys.argv or os.sep, you've already used another module's variables and constants.
Because the way you share variables and constants is exactly the same way you share functions and classes.
In fact, functions, classes, variables, constants—they're all just module-global variables as far as Python is concerned. They may have values of different types, but they're the same kind of variable.
So, let's say you write this module:
# spam.py
cheese = ['Gouda', 'Edam']
def breakfast():
print(cheese[-1])
If you import spam, you can use cheese, exactly the same way you use eggs:
import spam
# call a function
spam.eggs()
# access a variable
print(spam.cheese)
# mutate a variable's value
spam.cheese.append('Leyden')
spam.eggs() # now it prints Leyden instead of Edam
# even rebind a variable
spam.cheese = (1, 2, 3, 4)
spam.eggs() # now it prints 4
# even rebind a function
spam.eggs = lambda: print('monkeypatched')
spam.eggs()
C++ header files are really just a poor man's modules. Not every language is as flexible as Python, but almost every language from Ruby to Rust has some kind of real module system; only C++ (and C) requires you to fake it by having code that gets included into a bunch of different files at compile time.
If you are just looking to make function definitions, then this post may answer your question:
Python: How to import other Python files
Then you can define a function as per here:
https://www.tutorialspoint.com/python/python_functions.htm
Or if you are looking to make a class:
https://docs.python.org/3/tutorial/classes.html
You can look at example 3.9.5 in the previous link in order to understand how to create a shared variable among different object instances.

How do you declare a global constant in Python?

I have some heavy calculations that I want to do when my program starts, and then I want to save the result (a big bumpy matrix) in memory so that I can use it again and again. My program contains multiple files and classes, and I would like to be able to access this variable from anywhere, and if possible define it as constant.
How do you define a global constant in Python?
You can just declare a variable on the module level and use it in the module as a global variable. An you can also import it to other modules.
#mymodule.py
GLOBAL_VAR = 'Magic String' #or matrix...
def myfunc():
print(GLOBAL_VAR)
Or in other modules:
from mymodule import GLOBAL_VAR
I do not think the marked as good answer solves the op question. The global keyword in Python is used to modify a global variable in a local context (as explained here). This means that if the op modifies SOME_CONSTANT within myfunc the change will affect also outside the function scope (globally).
Not using the global keyword at the begining of myfunc is closer to the sense of global constant than the one suggested. Despite there are no means to render a value constant or immutable in Python.
There is no way to declare a constant in Python. You can just use
SOME_CONSTANT = [...]
If the file name where it is declared is file1.py, then you can access to it from other files in the following way:
import file1
print file1.SOME_CONSTANT
Assuming that both files are in the same directory.
I am not sure what you mean by 'global constant'; because there are no constants in Python (there is no "data protection", all variables are accessible).
You can implement a singleton pattern, but you will have to regenerate this at runtime each time.
Your other option will be to store the results in an external store (like say, redis) which is accessible from all processes.
Depending on how big your data set is, storing it externally in a fast K/V like redis might offer a performance boost as well.
You would still have to transform and load it though, since redis would not know what a numpy array is (although it has many complex types that you can exploit).

Accessing class instance from another module (Python)

I'm pretty new to Python as to OOP in general which is probably be the reason that I can't figure out the following:
I'm writing a python script which opens a text file and subsequently translates it into HTML, maintaining it's "own" mirrored directory-trees for the edit files and the html files.
Since directory creation and deletion is done automatically depending on, among other criteria, whether the file existed before or not, I need some kind of automatic and dynamic path adjustment. The script has to do several checks for files and associated directories before it can set the corresponding paths and start the processing.
I decided to put most of the more general functions (check file existence, show dialogs for duplicate filenames if found, etc) in a separate module, since they are quite specific and not depending on any state. Actually they create the state (path variables), so a class would not make sense if this is not a misconception.
On the other hand I'm using a class for the pure getting and setting the paths since I need the paths accessible from every module, so it's basically a global access point for paths.
This class is instantiated in the main module.
Now my problem is that I can't figure out how to manipulate the paths (using the path
setters) of that instance in the main module from a function inside the tools module. Importing the class instance or the main module into the tools module doesn't seem to work.
Generally speaking, is it possible to use a class instance across all module files and is this the way to go, or am I missing the point somehow?
I paste the relevant bits of code for illustration:
Setter/Getter class inside the main module
class SetEnv():
def __init__(self):
pass
def set_path_srcfile(self, path_srcfile):
self.path_srcfile = path_srcfile
def set_path_htmlfile(self):
self.path_htmlfile = self.path_srcfile.replace('source', 'html', 1).replace('.txt', '.html', 1)
def get_path_srcfile(self):
return self.path_srcfile
def get_path_htmlfile(self):
return self.path_htmlfile
Later in main_module:
env = SetEnv()
Part of tools module (inside a def acting upon user input):
import main_module as mm
path_srcfile = dict[int(user_option)][1] # dictionary holding the path we want to set
mm.env.set_path_srcfile(path_srcfile)
mm.env.set_path_htmlfile()
I might be misinterpreting your question, correct me if I am. As I understand it, you are using one single instance of a SetEnv object across an entire project to store and modify some path configuration.
If you really want a singleton like settings object, then use a module instead of a class.
# env.py
_src = ''
_html = ''
def set_path_srcfile(path_srcfile):
global _src
_src = path_srcfile
def get_path_srcfile():
return _src
...
Then everywhere you need it you can use import env; env.set_path_srcfile(myfile) and know that all other functions / modules / classes will be aware of the update.
If you don't want a singleton, then making a settings object available in the main module somewhere (as you have done) is a fine solution.

Python namespaces: How to make unique objects accessible in other modules?

I am writing a moderate-sized (a few KLOC) PyQt app. I started out writing it in nice modules for ease of comprehension but I am foundering on the rules of Python namespaces. At several points it is important to instantiate just one object of a class as a resource for other code.
For example: an object that represents Aspell attached as a subprocess, offering a check(word) method. Another example: the app features a single QTextEdit and other code needs to call on methods of this singular object, e.g. "if theEditWidget.document().isEmpty()..."
No matter where I instantiate such an object, it can only be referenced from code in that module and no other. So e.g. the code of the edit widget can't call on the Aspell gateway object unless the Aspell object is created in the same module. Fine except it is also needed from other modules.
In this question the bunch class is offered, but it seems to me a bunch has exactly the same problem: it's a unique object that can only be used in the module where it's created. Or am I completely missing the boat here?
OK suggested elsewhere, this seems like a simple answer to my problem. I just tested the following:
junk_main.py:
import junk_A
singularResource = junk_A.thing()
import junk_B
junk_B.handle = singularResource
print junk_B.look()
junk_A.py:
class thing():
def __init__(self):
self.member = 99
junk_B.py:
def look():
return handle.member
When I run junk_main it prints 99. So the main code can inject names into modules just by assignment. I am trying to think of reasons this is a bad idea.
You can access objects in a module with the . operator just like with a function. So, for example:
# Module a.py
a = 3
>>> import a
>>> print a.a
3
This is a trivial example, but you might want to do something like:
# Module EditWidget.py
theEditWidget = EditWidget()
...
# Another module
import EditWidget
if EditWidget.theEditWidget.document().isEmpty():
Or...
import * from EditWidget
if theEditWidget.document().isEmpty():
If you do go the import * from route, you can even define a list named __all__ in your modules with a list of the names (as strings) of all the objects you want your module to export to *. So if you wanted only theEditWidget to be exported, you could do:
# Module EditWidget.py
__all__ = ["theEditWidget"]
theEditWidget = EditWidget()
...
It turns out the answer is simpler than I thought. As I noted in the question, the main module can add names to an imported module. And any code can add members to an object. So the simple way to create an inter-module communication area is to create a very basic object in the main, say IMC (for inter-module communicator) and assign to it as members, anything that should be available to other modules:
IMC.special = A.thingy()
IMC.important_global_constant = 0x0001
etc. After importing any module, just assign IMC to it:
import B
B.IMC = IMC
Now, this is probably not the greatest idea from a software design standpoint. If you just limit IMC to holding named constants, it acts like a C header file. If it's just to give access to singular resources, it's like a link extern. But because of Python's liberal rules, code in any module can modify or add members to IMC. Used in an undisciplined way, "who changed that" could be a debugging issue. If there are multiple processes, race conditions are a danger.
At several points it is important to instantiate just one object of a class as a resource for other code.
Instead of trying to create some sort of singleton factory, can you not create the single-use object somewhere between the main point of entry for the program and instantiating the object that needs it? The single-use object can just be passed as a parameter to the other object. Logically, then, you won't create the single-use object more than once.
For example:
def main(...):
aspell_instance = ...
myapp = MyAppClass(aspell_instance)
or...
class SomeWidget(...):
def __init__(self, edit_widget):
self.edit_widget = edit_widget
def onSomeEvent(self, ...):
if self.edit_widget.document().isEmpty():
....
I don't know if that's clear enough, or if it's applicable to your situation. But to be honest, the only time I've found I can't do this is in a CherryPy-based webserver, where the points of entry were pretty much everywhere.

Sharing variables acoss several python files

I have tasked to modify a wx python gui based program which has several .py files.
I would like to share some variables defined in a.py and use them in b.py
The 10 -15 variables are of this form:
Amode = [SINGLE]
Format = [A] etc...
I would like to use them in b.py.
How do I go about it? I read about Pickle but still not clear how to use it well.
import a
// do something with a.Amode
// do something with a.Format
Generally, the best idea, in this case, is to either place the variables on the module directly or use some shared dataStore. I like the Borg pattern for this.
Basically do this:
#in borg.py
class Borg:
__shared_state = {}
def __init__(self):
self.__dict__ = self.__shared_state
Everywhere else:
import borg
drone = borg.Borg()
drone.foo = 1;
Obviously, you can limit this by defining __set__.
As to placing variables on modules directly, well, I'm not really a fan of having stateful variables publicly accessible on modules, but that is probably mostly me.
Modules are singletons (no matter how many times it's imported, it's only actually imported once, and that once is shared), so what I often do for this use case is to create a modules named, say, "shared.py", and put the data I want shared across other modules in it. Then, in those other modules:
import shared
# Use a shared variable/object
print shared.Amode
# Changes to the shared data are seen in all modules where it's imported.
shared.Amode = aNewValue
This has the nice effect of keeping all my shared data in its own namespace, "shared".

Categories

Resources