Behavior of import in python [duplicate] - python

This question already has answers here:
Does python optimize modules when they are imported multiple times?
(6 answers)
Closed 3 years ago.
Is it safe to assume that python module is calculated once?
If module A contains CONST_A = json.load(...) and is imported multiple times in different files of the same program and different threads, will it be calculated/executed just once?
If not, when the CONST_A be recalculated? And would the next structure fix it?
module CALCULATE_CONST_A
import json
CONST_A = json.load(open(...))
module A
from CALCULATE_CONST_A import CONST_A
further imports of A...
Final question: What are the best practices for creating precalculated constants?

Well, let's experiment:
tbi.py
print("Hello, World!")
file1.py
import tbi
print("This is file1")
file2.py
import file1
import tbi
print("This is file2")
And now, when we run file2, we see:
$ python file2.py
Hello, World!
This is file1
This is file2
So the answer to your question is yes, python modules are executed once only. If tbi.py were executed twice, we would have seen "Hello World" printed twice. It's logical, then, to conclude that the attributes of the file are set the first time that file is imported.
Furthermore, more experimentation can show you that, if I put a global variable in tbi, and both file1 and file2 modified it, they would both be modifying the same object. This is visible in a number of built-in packages: for example, changing the value of sys.stdout (the file descriptor for standard output, and a global variable specified when the sys module is first loaded) changes it for the entire program, not just the file that modified it.
If you're worried about this sort of thing causing errors, the best thing to do is to not use global variables - instead, use classes and assign them default values when constructed.

Related

Why does Python allow a module to import itself? [duplicate]

This question already has answers here:
Python program importing itself
(4 answers)
Closed 3 months ago.
In a simple Program in BugTest.py:
from BugTest import *
print("Hello World")
note my error in importing BugTest.py from BugTest.py
Here is the output:
Hello World
Hello World
My question is: Why doesn't this cause a compile error? Is this a bug in Python?
Why does it only import twice, rather than enter an infinite loop?
Why doesn't this cause a compile error?
Because it's completely valid syntax. The only error (absent a problem in the Python runtime itself, such as running out of memory or failing to find the source code) that can occur at compile time in Python is SyntaxError. Names are only resolved at runtime.
That said, it's also completely valid at runtime.
Why does it only import twice, rather than enter an infinite loop?
from BugTest import * means - roughly - "look for an existing module named BugTest; if not found, find and load BugTest.py, create a module object from it named BugTest, and put it in the module cache. Then, copy all the names from the BugTest module into the current module (overwriting any existing names)."
When you run the program, Python creates a module object from the BugTest.py code, and (very usefully) gives it the special name __main__. Then it runs the top-level code, triggering the import statement. Now it creates another module object from the BugTest.py code, giving it the usual name of BugTest. That module's top-level code runs as well; but when it tries to import, a BugTest module is already in the module cache.
You executed
$ python BugTest.py
which asked for two statements to run,
an import and a print.
The pair of statements ran exactly once.
The first statement performed an import,
which has the side effect of printing a line.
Then the second statement, a print,
printed a line as requested.
Everything happened according to plan.
It is usually considered undesirable for
an import to have side effects
such as print().
In this case, of course,
it makes perfectly good sense
during debugging.
Once imported,
a module appears in a hash table
and will not be re-imported again.
So attempting a double import
here would not provoke three lines of output.
That is, having done (a possibly time
consuming) import x,
we won't see x imported again.
If top-level, or any transitive
dependencies imported by top-level,
asks for import x, it is simply
skipped, as a cache hit.

python importing a function in which I define a global variable [duplicate]

This question already has an answer here:
Get variable from another file - python
(1 answer)
Closed 4 years ago.
I'm having difficulty accessing a variable.
I'm working toward the following, calling python script from bash, with arguments, which then imports a function defined in a second python script, executes it and thereby creates a variable which will be used later in the first python script.
At the moment,to test I'm copying and pasting directly into a Python terminal some commands like this:
from script2 import *
foofunction(arg)
print(newlist)
The foo function defined in script2 is executing, I can see files have been written but when I try to print the list supposedly created while executing the imported function, I get a message telling me it's undefined.
Inside my script2.py, i made sure to enter a statement
global newlist
before defining its length and populating it.
I'm scratching my head at this stage.
You should refer to newlist and the module where it is defined like this:
from script2 import *
foofunction(arg)
print(script2.newlist)

Run code from other Python file while reflecting changes to other file [duplicate]

This question already has answers here:
How to re import an updated package while in Python Interpreter? [duplicate]
(11 answers)
Closed 6 years ago.
Consider the following Python (2.7.9) code:
test.py
import test2
import time
while True:
print test2.getData()
time.sleep(1)
test2.py
def getData ():
return [1,2,3]
Running with:
python -u test.py
If I modify test2.py while test.py is running (say, changing it to return [4,5,6]), the output of test.py does not change. This is not unexpected.
However, I'd like changes to test2.py to be reflected in the output. Is there a way to do this? E.g. something like reparsing test2.py every time test2.getData() is invoked?
Other things tried, from comments:
Moving import test2 into the loop.
Removing test2.pyc while test is running (with import in and out of loop).
If I recall properly, python code will be converted in to a byte code before being executed so there are no ways of changing the code when running it.
What I suggest you do is to create a global variable or a class instead and change that instead. Alternate solution will be to write the data to a file but doesn't benefit much since it needs access to the file system and will not be as fast as variables.

How do I find out the file that is the beginning of a Python program? [duplicate]

This question already has answers here:
Find path to currently running file
(8 answers)
Closed 7 years ago.
Let's assume that I have a program that consists of at least two files, magic.py which is part of the herebemagic module...
def foo():
# This line is what my question will be all about
pass
...and main.py, which starts the program:
import os
from herebemagic import magic
print("This is where this file lies: %s" % (repr(os.path.abspath(__file__)), ))
magic.foo()
As demonstrated, finding a module's file, and the path that it is in, is trivial. But how would I, in magic.py, get a reference to main.py's module (being the one that was invoked by the interpreter, not necessarily the one that imported herebemagic directly), so that I can get at its file?
Of course I could just figure it out in main.py, and pass it down to foo(), but in practice there can be an arbitrary number of modules in between the two, and in my case, it'd be ugly to pass it down (I'm loading a lot of modules with importlib, and the information is currently only relevant to one of the modules). Or I could use a builtin, but that is a namespace that no one wants to litter.
The Python executable is called with the name of the main script as command line argument. Python keeps this in sys.argv:
sys.argv[0]

Pass variable between python scripts

I'm sure this is very simple but I've been unable to get it working correctly. I need to have my main python script call another python script and pass variables from the original script to the script that I've called
So for a simplistic example my first script is,
first.py
x = 5
import second
and my second script is,
second.py
print x
and I would expect it to print x but I get
NameError: name 'x' is not defined
I'm not sure if import is right way to achieve this, but if someone could shed light on it in a simple way that would be great!
thanks,
EDIT
After reading the comments I thought I would expand on my question. Aswin Murugesh answer fixes the import problem I was having, however the solution does not have the desired outcome as I can not seem to pass items in a list this way.
In first.py I have a list which I process as follows
for insert, (list) in enumerate(list, start =1):
'call second.py passing current list item'
I wanted to pass each item in the list to a second python file for further processing (web scraping), I didn't want to do this in first.py as this is meant to be the main 'scan' program which then calls other programs. I hope this now make more sense.
Thanks for the comments thus far.
When you call a script, the calling script can access the namespace of the called script. (In your case, first can access the namespace of second.) However, what you are asking for is the other way around. Your variable is defined in the calling script, and you want the called script to access the caller's namespace.
An answer is already stated in this SO post, in the question itself:
Access namespace of calling module
But I will just explain it here in your context.
To get what you want in your case, start off the called script with the following line:
from __main__ import *
This allows it to access the namespace (all variables and functions) of the caller script.
So now your calling script is, as before:
x=5
import second
and the called script is:
from __main__ import *
print x
This should work fine.
use the following script:
first.py:
x=5
second.py
import first
print first.x
this will print the x value. Always imported script data should be referenced with the script name, like in first.x
To avoid namespace pollution, import the variables you want individually: from __main__ import x, and so on. Otherwise you'll end up with naming conflicts you weren't aware of.
Try use exec
Python3.5:
first.py
x=5
exec(open('second.py').read())
second.py
print(x)
You can also pass x by using:
x=5
myVars = {'x':x}
exec(open('second.py').read(), myVars)
Not sure if this is a good way.
Finally,
I created a package for Python to solve this problem.
Install Guli from PIP.
$ pip install guli
Guli doesn't require installing any additional PIP package.
With the package you can
Guli can be used to pass between different Python scripts, between many processes or at the same script.
pass variables between main Process and another (Multiprocess) Process.
Pass variables between different Python scripts.
Pass variables between 'Main Process' and another (Multiprocess) Process.
Use variables at the same script.
Create / Delete / Edit - GuliVariables.
Example
import guli
import multiprocessing
string = guli.GuliVariable("hello").get()
print(string) # returns empty string ""
def my_function():
''' change the value from another process '''
guli.GuliVariable("hello").setValue(4)
multiprocessing.Process(target=my_function).start()
import time
time.sleep(0.01) # delay after process to catch the update
string = guli.GuliVariable("hello").get()
print(string) # returns "success!!!"
Hope I solved the problem for many people!

Categories

Resources