Global Variable across modules - python

I faced this problem while i was expirementing with my project.My project is designed so it has multipule submoudles.
Now each submodule needs a position of an the same item on the screen,which is random each time the program ran.I thought it was a good idea to check once where is the position of the item (It does not change in runtime) , and let all modules access the position.(Since checking the position takes a long time)
This is what i did:
main.py
import Config
import sub_module
main()
def main():
position = get_pos()
Config.pos = position
sub_module.click_on_item()
Config.py
pos = None
I tried using this code , so when i ran the program , it sets the config.py module pos variable , to the position of the item on screen.
This code works fine but when i try to use it in the submodules like this:
sub_module.py
import Config
def click_on_item():
click(Config.pos)
It resets the value to None , since it reruns the Config module code.
Is there an elegant solution for this problem ? I can't let the position as an argument for the , since my case is much more complex.
One solution that i can think of is writing to the disk , and rereading but it's not fast.
Thanks for the help.
2 EDIT:
My project is multi-package , and there is the problem
this is the directory tree:
mainPackage:
__init__.py
Config.py
main.py
b.py
Packages:
Package_A:
__init__.py
a.py
main.py
import Config
from Packages.Package_A import a
import b
def main():
Config.Position = (124, 586)
a.print_val()
b.print_val()
if __name__ == '__main__':
main()
Config
Position = None
b.py
import Config
def print_val():
print Config.Position
a.py
from mainPackage import Config
def print_val():
print Config.Position
output
None -> from Package_A
(124, 586) -> from b.py
Sorry for the inconvenience since i didn't know what was causing the problem , my interest is in multi package global variable.

The problem is in a.py: from mainPackage import Config. You did an absolute import from a package and ended up importing Config twice. Python only imports a module once but in your case you used two different names (Config in some files, mainPackage.Config in others) which confused python and it imported the module twice - once by a package relative import and once by an absolute import. Add print "Importing Config" to Config.py and you will see it printed twice.
Just change a.py to import Config and all will be well.

Config.py will only be initialized on import once in your application and pos will be initially None.
main.py then sets it, and all other modules can access pos with Config.pos.
Config.py
# Initial value
pos = None
main.py
import Config
import sub_module
def main():
position = get_pos()
Config.pos = position
sub_module.click_on_item()
The rest of your files can be kept as is.
UPDATE
As #tdelaney mentioned in his answer.
Change
from mainPackage import Config
to
import Config
to avoid another Config.

For each of your module, define your functions/class with a 'pos' argument.
Module A.py
def foo(pos):
click(pos)
Module main.py
def main():
position = get_pos()
A.foo(position)
In general, do not use global var.

Related

Importing from cousin module in Python

I have the following structure:
LICENSE.md
README.md
requirements.txt
src
routes
route_a.py
__ init __.py
util
__ init __.py
db.py
And in db.py, I have something that looks like this:
import mysql.connector
def get_value():
# Query database using mysql.connector
return value
value = get_value()
def query_that_uses_value(value):
# do stuff with value
return value2
I want to be able to use value inside of route_a.py and also inside of other functions in db.py. What's the best way to do this?
import sys
sys.path.insert(0, "path")
that's how I did it.
the path is the folder u want to use I would choose the main folder so u have the same starting point for your imports.
in your case, the import would look like this
from util.dp.py import get_value
if you have this at the start of your programme that u want the function imported to
sys.path.insert(0,"path_to_src/src")
but path to src must be an absolut path beginning from your root folder
In route_a.py, simply import the variable value (and other functions you need) from ..util.db, which is a relative import that will reference src/util/db.py. Here's what the file src/routes/route_a.py should contain:
from ..util.db import value, function1, function2
Best way to deal with imports is to export PYTHONPATH=$(pwd) in your project root directory where there are src, requirements.txt, etc.
So in your terminal, run export PYTHONPATH=$(pwd) and all your imports should be consistent and start from src.
For example:
from src.util.db import value
from src.routes.route_a import something
Note that everytime you open a new terminal you should run export PYTHONPATH=$(pwd) cause this is not permanent. When your terminal disappears your PYTHONPATH should reset and that's a good thing and is best practice.
Also don't forget to run everything from src. Like: python src/util/db.py
If you follow this structure, I promise you will never have any import problems.

Importing a function from another directory within a package

I am working with the following directory in Python3.8:
package/
__init__.py
/folder1
__init__.py
file1.py
/folder2
__init__.py
file2.py
/folder3
__init__.py
file3.py
I would like to import a function from file3 into file2. What is the easiest way to do it? I would also like to avoid manually appending to PYTHONPATH, to make this as smooth as possible for the next person pulling the project.
So far tried relative imports, which didn't work, possibly because I did not specify something in the init, which is currently empty. The error I am getting using:
from ..package.folder3.file3 import function_name
is
ImportError: attempted relative import with no known parent package
Thanks for all help!
The answer to your question is pretty simple, you need to add your package path to the system path.
Here is a complete example:
In file3.py, let's create a simple function
def func():
print("Hello from file3")
In file2.py, we can import func function like so:
import os
import sys
sys.path.append(os.path.abspath('../../..'))
# import func now from file3
from package.folder3.file3 import func
func() #should return "Hello from file3"
Hopefully, this answers your question!

import a dictionary built at run-time

My code is structured as follows:
main.py
utils.py
blah.py
The main module uses argparse to read in the location of a configurations yaml file which is then loaded as a dictionary. Is there a way for utils and blah to import this built-up dictionary?
Edit: I tried using from main import config (config being the dictionary I built) but I get ImportError: cannot import name 'config' from 'main'
Edit2: Main imports the other 2 modules - apologies for leaving out this very important detail
I would recommend making another file, say, globals.py. Import this in main, utils, and blah, and set properties in it to be recalled by the other modules. For example:
globals.py
configs = {}
main.py
import .globals
...
user_configs = yaml.load('user/entered/path.yml')
globals.configs.update(user_configs) # modifies the global `configs` variable
utils.py
import .globals
...
# need to use one of the configs for something:
try:
relevant_config = globals.configs['relevant_config']
except KeyError:
print("User did not input the config field 'relevant_config'")
All modules will be able to see the same globals instance, thus allowing you to use what are effectively global variables across your program.
You could simply save configs as a gobal variable in main.py and have utils.py and blah.py import .main, but having a designated module for this is cleaner and clearer than to have other modules importing the main module.
Just do
import main
and use it as
main.dictionary
That should do it!

Python - why can I import modules without __init__.py at all?

I'm new to Python and I still can't get my head around why we need a __init__.py file to import modules. I have gone through other questions and answers, such as this.
What confuses me is that I can import my modules without __init__py, so why do I need it at all?
My example,
index.py
modules/
hello/
hello.py
HelloWorld.py
index.py,
import os
import sys
root = os.path.dirname(__file__)
sys.path.append(root + "/modules/hello")
# IMPORTS MODULES
from hello import hello
from HelloWorld import HelloWorld
def application(environ, start_response):
results = []
results.append(hello())
helloWorld = HelloWorld()
results.append(helloWorld.sayHello())
output = "<br/>".join(results)
response_body = output
status = '200 OK'
response_headers = [('Content-Type', 'text/html'),
('Content-Length', str(len(response_body)))]
start_response(status, response_headers)
return [response_body]
modules/hello/hello.py,
def hello():
return 'Hello World from hello.py!'
modules/hello/HelloWorld.py,
# define a class
class HelloWorld:
def __init__(self):
self.message = 'Hello World from HelloWorld.py!'
def sayHello(self):
return self.message
Result,
Hello World from hello.py!
Hello World from HelloWorld.py!
What it takes is just these two lines,
root = os.path.dirname(__file__)
sys.path.append(root + "/modules/hello")
Without any of __init__py. Can someone explain why it works in this way?
If __init__py is the proper way, what should I do/change in my code?
Based on this link: Since Python 3.3
Allowing implicit namespace packages means that the requirement to provide an __init__.py file can be dropped completely
__init__.py is for packages. A package contains a collection of related modules. If you just have a single module you want to use, you don't need to use __init__.py; just put the single .py file somewhere on the system path and you can import it.
The purpose of packages is not just to allow you to import the modules inside them. It's to group the modules together. The main benefit of this is that, if a module is inside a package, then that module can import other modules from the package using relative imports. If you have foo.py and bar.py in the same package, then foo can just do from . import bar. This makes intra-package imports more compact and easier to reorganize if you restructure the package or change its name.
Also, an obvious benefit is. . . if you make it a package, you don't have to do that sys.path stuff every time you want to import something from it.
I think that this might be due to Python version you are using. I did some experimentation and found out that having following structure:
jedrzej#jedrzej-UX303LB ~/temp $ tree .
.
├── main.py
└── packages
├── file.py
└── file.pyc
1 directory, 5 files
content of main.py:
import packages.file as p
p.fun()
and content of file.py:
import sys
def fun():
print(sys.path)
When I am executing main.py with Python 2.7.12 I get ImportError while execution of main.py with Python 3.5.2 simply works.
After adding __init__.py in packages directory, code works with both versions of Python.
Files named __init__.py are used to mark directories on disk as Python package directories. If you have the files
modules/spam/__init__.py
modules/spam/module.py
and modules is in your path, you can import the code in module.py as
import spam.module
or
from spam import module
If you remove the __init__.py file, Python will no longer look for submodules inside that directory, so attempts to import the module will fail.
The __init__.py file is usually empty, but can be used to export selected portions of the package under a more convenient name, hold convenience functions, etc. Given the example above, the contents of the init module can be accessed with
import spam
And finally here is what the official documentation has to say about this file:
The __init__.py files are required to make Python treat the
directories as containing packages; this is done to prevent
directories with a common name, such as string, from
unintentionally hiding valid modules that occur later on the
module search path. In the simplest case, __init__.py can just
be an empty file, but it can also execute initialization code
for the package or set the __all__ variable, described later.
I think this is a good 'answer' for what I didn't understand.
myMath/
__init__.py
adv/
__init__.py
sqrt.py
fib.py
add.py
subtract.py
multiply.py
divide.py
myMath/__init__.py
from add import add
from divide import division
from multiply import multiply
from subtract import subtract
from adv.fib import fibonacci
from adv.sqrt import squareroot
index.py
import sys
sys.path.append('C:\Users\mdriscoll\Documents')
import mymath
print mymath.add(4,5)
print mymath.division(4, 2)
print mymath.multiply(10, 5)
print mymath.fibonacci(8)
print mymath.squareroot(48)

Python Static Variable

I'm creating an application that uses a base class to hold all of the configuration values, import methods, etc.
/
- application.py
+ class foo
+ config = None
+ def loadconfig
- otherfile.py
+ class bar
+ def getconfigvalue
So, if I start application.py and it runs loadconfig, which loads a value into foo.config, and then imports (inside said function - to get around circular imports) otherfile.py and creates a new bar object, which then tries to get a configuration value from foo.config, but says that foo.config is equal to None. Any suggestions?
Simplified code:
main.py
class Main:
config = None
#staticmethod
def start():
## Load the configuration from a file, creating a dict in Main.config ##
Main.other()
#staticmethod
def other():
from otherfile import otherclass
otherclass()
Main.start()
otherfile.py
from main import Main
class otherclass:
def __init__(self):
print(Main.config) ## Prints "None"
Note: It was arranged like this because that's how it actually works in the program; I feel like it has something to do with scope
Full source files:
asgard.py: http://pastebin.com/jRkWzrPq
library/childcontainer.py: http://pastebin.com/6a561Nun
I'll work from what I believe your issue is with asgard, because your simplified example is broken:
You can't run main.py because of a circular import, yet I believe it was main.py you intended to be running (running otherfile.py won't exhibit the problem I believe you're running into).
You're never actually assigning anything to Main.config. I'm not sure precisely where you were intending to assign to it.
Anyway, on to asgard.py.
Here you run into the problem of the module __main__. When you run asgard.py, its __name__ is __main__; something you may not be aware of is that this is literally its module name as it appears in sys.modules - the main module is sys.modules['__main__'], not sys.modules['asgard']. Then, when you import library.childcontainer, it tries to import asgard. This looks up sys.modules['asgard'], which doesn't exist, and so it imports the contents of asgard.py into a new module object.
If you were to have another file main.py which did import asgard; asgard.Asgard.initialize() (ignoring the conditional imports problem I mention below), you wouldn't run into this problem because the __main__ module would be of that main.py, and asgard.py would only ever be imported with the name asgard. Another solution which would work would be if __name__ == '__main__': sys.modules['asgard'] = sys.modules['__main__'].
And please, please, please don't ever pull that if __name__ == '__main__': import ... trick. This means that if you try to import asgard; asgard.Asgard.initialize(), for example, it will fail saying that the name 'os' is undefined. Please put these imports at the top of the file, where they belong.

Categories

Resources