How to import variable from another function and another directory? - python

I have two files.
first.py
Class Repo:
def my_function:
variable = []
Now, I've second file in different directory and want to create something like:
second.py
def my_second_function(variable):
print(variable) # or some other operations on variable
What can I do to make my above code works? I tried something like:
import sys
sys.path.insert(1, 'path')
from first import *
but it doesn't work. Do you have any ideas?

Although it is not entirely clear to me what you are aiming at, here is a way to define a global variable within one file, which then can be imported via the sys.path approach you tried:
test_dir/file1.py:
global_var1 = 'global_var1' # This variable is available upon import of file1.py
def fun():
global global_var2
global_var2 = 'global_var2' # This variable will be available after having called fun()
file2.py:
import sys
sys.path.insert(1, 'test_dir')
import file1
print(file1.global_var1)
#print(file1.global_var2) # This would fail
file1.fun()
print(file1.global_var2) # This works

Related

Python - How can I pass variables from one skript to skript? [duplicate]

How can I import variables from one file to another?
example: file1 has the variables x1 and x2 how to pass them to file2?
How can I import all of the variables from one to another?
from file1 import *
will import all objects and methods in file1
Import file1 inside file2:
To import all variables from file1 without flooding file2's namespace, use:
import file1
#now use file1.x1, file2.x2, ... to access those variables
To import all variables from file1 to file2's namespace( not recommended):
from file1 import *
#now use x1, x2..
From the docs:
While it is valid to use from module import * at module level it is
usually a bad idea. For one, this loses an important property Python
otherwise has — you can know where each toplevel name is defined by a
simple “search” function in your favourite editor. You also open
yourself to trouble in the future, if some module grows additional
functions or classes.
Best to import x1 and x2 explicitly:
from file1 import x1, x2
This allows you to avoid unnecessary namespace conflicts with variables and functions from file1 while working in file2.
But if you really want, you can import all the variables:
from file1 import *
Actually this is not really the same to import a variable with:
from file1 import x1
print(x1)
and
import file1
print(file1.x1)
Altough at import time x1 and file1.x1 have the same value, they are not the same variables. For instance, call a function in file1 that modifies x1 and then try to print the variable from the main file: you will not see the modified value.
first.py:
a=5
second.py:
import first
print(first.a)
The result will be 5.
script1.py
title="Hello world"
script2.py is where we using script1 variable
Method 1:
import script1
print(script1.title)
Method 2:
from script1 import title
print(title)
Marc response is correct. Actually, you can print the memory address for the variables print(hex(id(libvar)) and you can see the addresses are different.
# mylib.py
libvar = None
def lib_method():
global libvar
print(hex(id(libvar)))
# myapp.py
from mylib import libvar, lib_method
import mylib
lib_method()
print(hex(id(libvar)))
print(hex(id(mylib.libvar)))
if you need to import of a variable from a dir on the same level or below you can use "import_module" coming from you cwd of the project:
from importlib import import_module
mod = import_module(
f"{cwd}.source.myfolder.myfile"
)
var = getattr(mod, "my_variable")

Global Variable across modules

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.

Global variable from multiple file in python [duplicate]

I'm bit confused about how the global variables work. I have a large project, with around 50 files, and I need to define global variables for all those files.
What I did was define them in my projects main.py file, as following:
# ../myproject/main.py
# Define global myList
global myList
myList = []
# Imports
import subfile
# Do something
subfile.stuff()
print(myList[0])
I'm trying to use myList in subfile.py, as following
# ../myproject/subfile.py
# Save "hey" into myList
def stuff():
globals()["myList"].append("hey")
An other way I tried, but didn't work either
# ../myproject/main.py
# Import globfile
import globfile
# Save myList into globfile
globfile.myList = []
# Import subfile
import subfile
# Do something
subfile.stuff()
print(globfile.myList[0])
And inside subfile.py I had this:
# ../myproject/subfile.py
# Import globfile
import globfile
# Save "hey" into myList
def stuff():
globfile.myList.append("hey")
But again, it didn't work. How should I implement this? I understand that it cannot work like that, when the two files don't really know each other (well subfile doesn't know main), but I can't think of how to do it, without using io writing or pickle, which I don't want to do.
The problem is you defined myList from main.py, but subfile.py needs to use it. Here is a clean way to solve this problem: move all globals to a file, I call this file settings.py. This file is responsible for defining globals and initializing them:
# settings.py
def init():
global myList
myList = []
Next, your subfile can import globals:
# subfile.py
import settings
def stuff():
settings.myList.append('hey')
Note that subfile does not call init()— that task belongs to main.py:
# main.py
import settings
import subfile
settings.init() # Call only once
subfile.stuff() # Do stuff with global var
print settings.myList[0] # Check the result
This way, you achieve your objective while avoid initializing global variables more than once.
See Python's document on sharing global variables across modules:
The canonical way to share information across modules within a single program is to create a special module (often called config or cfg).
config.py:
x = 0 # Default value of the 'x' configuration setting
Import the config module in all modules of your application; the module then becomes available as a global name.
main.py:
import config
print (config.x)
In general, don’t use from modulename import *. Doing so clutters the importer’s namespace, and makes it much harder for linters to detect undefined names.
You can think of Python global variables as "module" variables - and as such they are much more useful than the traditional "global variables" from C.
A global variable is actually defined in a module's __dict__ and can be accessed from outside that module as a module attribute.
So, in your example:
# ../myproject/main.py
# Define global myList
# global myList - there is no "global" declaration at module level. Just inside
# function and methods
myList = []
# Imports
import subfile
# Do something
subfile.stuff()
print(myList[0])
And:
# ../myproject/subfile.py
# Save "hey" into myList
def stuff():
# You have to make the module main available for the
# code here.
# Placing the import inside the function body will
# usually avoid import cycles -
# unless you happen to call this function from
# either main or subfile's body (i.e. not from inside a function or method)
import main
main.mylist.append("hey")
Using from your_file import * should fix your problems. It defines everything so that it is globally available (with the exception of local variables in the imports of course).
for example:
##test.py:
from pytest import *
print hello_world
and:
##pytest.py
hello_world="hello world!"
Hai Vu answer works great, just one comment:
In case you are using the global in other module and you want to set the global dynamically, pay attention to import the other modules after you set the global variables, for example:
# settings.py
def init(arg):
global myList
myList = []
mylist.append(arg)
# subfile.py
import settings
def print():
settings.myList[0]
# main.py
import settings
settings.init("1st") # global init before used in other imported modules
# Or else they will be undefined
import subfile
subfile.print() # global usage
Your 2nd attempt will work perfectly, and is actually a really good way to handle variable names that you want to have available globally. But you have a name error in the last line. Here is how it should be:
# ../myproject/main.py
# Import globfile
import globfile
# Save myList into globfile
globfile.myList = []
# Import subfile
import subfile
# Do something
subfile.stuff()
print(globfile.myList[0])
See the last line? myList is an attr of globfile, not subfile. This will work as you want.
Mike
I just came across this post and thought of posting my solution, just in case of anyone being in the same situation as me, where there are quite some files in the developed program, and you don't have the time to think through the whole import sequence of your modules (if you didn't think of that properly right from the start, such as I did).
In such cases, in the script where you initiate your global(s), simply code a class which says like:
class My_Globals:
def __init__(self):
self.global1 = "initial_value_1"
self.global2 = "initial_value_2"
...
and then use, instead of the line in the script where you initiated your globals, instead of
global1 = "initial_value_1"
use
globals = My_Globals()
I was then able to retrieve / change the values of any of these globals via
globals.desired_global
in any script, and these changes were automatically also applied to all the other scripts using them. All worked now, by using the exact same import statements which previously failed, due to the problems mentioned in this post / discussion here. I simply thought of global object's properties being changing dynamically without the need of considering / changing any import logic, in comparison to simple importing of global variables, and that definitely was the quickest and easiest (for later access) approach to solve this kind of problem for me.
Based on above answers and links within I created a new module called global_variables.py:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# ==============================================================================
#
# global_variables.py - Global variables shared by all modules.
#
# ==============================================================================
USER = None # User ID, Name, GUID varies by platform
def init():
""" This should only be called once by the main module
Child modules will inherit values. For example if they contain
import global_variables as g
Later on they can reference 'g.USER' to get the user ID.
"""
global USER
import getpass
USER = getpass.getuser()
# End of global_variables.py
Then in my main module I use this:
import global_variables as g
g.init()
In another child imported module I can use:
import global_variables as g
# hundreds of lines later....
print(g.USER)
I've only spent a few minutes testing in two different python multiple-module programs but so far it's working perfectly.
Namespace nightmares arise when you do from config import mySharedThing. That can't be stressed enough.
It's OK to use from in other places.
You can even have a config module that's totally empty.
# my_config.py
pass
# my_other_module.py
import my_config
def doSomething():
print(my_config.mySharedThing.message)
# main.py
from dataclasses import dataclass
from my_other_module import doSomething
import my_config
#dataclass
class Thing:
message: str
my_config.mySharedThing = Thing('Hey everybody!')
doSomething()
result:
$ python3 main.py
Hey everybody!
But using objects you pulled in with from will take you down a path of frustration.
# my_other_module.py
from my_config import mySharedThing
def doSomething():
print(mySharedThing.message)
result:
$ python3 main.py
ImportError: cannot import name 'mySharedThing' from 'my_config' (my_config.py)
And maybe you'll try to fix it like this:
# my_config.py
mySharedThing = None
result:
$ python3 main.py
AttributeError: 'NoneType' object has no attribute 'message'
And then maybe you'll find this page and try to solve it by adding an init() method.
But the whole problem is the from.

python import specific file

trying to import a specific file called environment.py
the issue is that I have this file in more than one location
the way i'm loading all my file variables (more than 20 variables in each file) is :
from environment import *
the thing is , I have the environment.py in 2 directories and my sys.path includes both of them. python loads the file from the first location in the list.
Tried
import os, sys, imp
path = os.path.dirname(os.path.abspath(__file__))
file = path + '/environment.py'
foo = imp.load_source('*',file)
But then my variables are loaded into foo and not directly.
Any ideas how to force import * from the right location
If you want to continue with what you started and this is in the global scope, you could add this to the end:
for varName in dir(foo):
globals()[varName] = getattr(foo, varName)
Now all of the variables that were defined in environment.py are in your global namespace.
Although it's probably easier to just do what Tom Karzes suggested and do:
import os, sys
sys.path.insert(0, path)
from environment import *
# Optional. Probably harmless to leave it in your path.
del sys.path[0]
Put it in a module
/module
__init__.py
environment.py
That way you can call
from module.environment import *
And there should be no issue having two modules with environment.py in them, the only difference being the import call. Is that what you mean?

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