Reputation: 2762
a.py:
import sys
h = 'this is h from a.py'
for i in sys.argv:
if i in ['-h']:
print(h)
b.py:
import sys
from a import h
h='this is h from b.py'
for i in sys.argv:
if i in ['-h']:
print(h)
Then I get:
>$ python b.py -h
this is h from a.py
this is h from b.py
Shouldn't 'h' have been overridden? Or is a.py accessing the '-h' argument given to b.py?
Thank you
Upvotes: 0
Views: 2209
Reputation: 293
You can overwrite the variable from b.py
with the following code:
import a
a.h = 'actually replaced value'
Note: actually adding that to a.py
will still give the following result:
>$ python b.py -h
this is h from a.py
this is h from b.py
First note that you can verify that the value of h gets changed with the following code:
a.py:
import sys
h = 'this is h from a.py'
for i in sys.argv:
if i in ['-h']:
print(h)
def what_is_h():
print('h:', h)
b.py:
import sys
from a import h, what_is_h
import a
what_is_h()
a.h = h = 'this is h from b.py'
what_is_h()
for i in sys.argv:
if i in ['-h']:
print(h)
This results in the following:
this is h from a.py
h: this is h from a.py
h: this is h from b.py
this is h from b.py
The first what_is_h
call shows the original h
value and the second shows the modified value. The problem is a.py
and b.py
seem to have different versions of the variable h
this is what is called scope. When you use the import
statement python parses your file and runs the code. The way you can prevent this automatic running of the code is by placing it in a function, importing it and running it from b.py
preferably passing h
as an argument (since global state is usually bad practice in python).
a.py
too but only if I run it directly?"Now if you want a function executed when you run a.py
or b.py
but run the function in a.py
only if it is run directly you can add the following to the bottom of your script file:
if __name__ == '__main__':
my_function()
This will run the function my_function
only when you execute $> python a.py
.
Note that when importing a.py
it will not run my_function
unless run otherwise.
How does this work?
__name__
is a built-in global variable that stores the "name" the python interpreter gives to python scripts. The file that is run is given the __name__
'__main__'
. Now when importing something from a.py
__name__
will equal 'a'
and my_function
will not run.
instead of
if i in ['-h']:
# ... your code
do
if i == '-h':
# ... your code
if you want to check for multiple flags later you can change it.
if you only want to check if -h
is in sys.args
you can do:
if '-h' in sys.args:
# ... your code
instead of
for i in sys.args:
if i == '-h':
# ... your code
If you plan to do more complex things with arguments there is library that should be included by default with every installation of python, namely the argparse library.
I hope I was able to help.
Upvotes: 2
Reputation: 995
When you import a, all the code inside a.py is executed, thence you will always have the printed output:
this is h from a.py
To avoid it, you can change a.py to:
import sys
h = 'this is h from a.py'
if __name__ == '__main__':
for i in sys.argv:
if i in ['-h']:
print(h)
This way, the code inside the if clause will only be executed when you call python a.py -h
, and not when you call python b.py -h
.
Upvotes: 1