This is test.py:
import sys
a = 50
b = [1,2]
def change():
print "Here 1"
import test
print "Here 2"
test.a = -1
test.b = [0,1]
return
def main():
print "Here 3"
change()
print "Here 4"
print a, b
if 1:
main()
The above python code when ran on system generates the following output:
Here 3
Here 1
Here 3
Here 1
Here 2
Here 4
-1 [0, 1]
Here 2
Here 4
50 [1, 2]
What I am confused why is not there an infinite loop of "Here 1 \n Here 3" outputs. How can the print a, b outputs can be justified?
When you run the file as a script, it is not considered to be the test module. It is considered to be the __main__ module.
When execution hits import test, a second execution of the file starts, where the module is considered to be test.
When execution hits import test again, Python recognizes that it's already importing test and does not reexecute the module. Instead, it merely loads the half-initialized test module object into the current namespace and continues on. Python's optimistic assumption is that you've written the code so that the contents of test won't be needed until the import finishes.
When execution hits the assignments to test.a and test.b, that affects the test module, but not __main__, despite the fact that they came from the same file. Thus, the print a, b from the imported module reflects the new values, while the print a, b from __main__ reflects the initial values.
A file can only be imported once. The 'import test' line succeeds the first time it is encountered. When it is encountered a second time, the interpreter will check that it has already been loaded.
When a program is initially run, it does not count as being 'imported'.
The general flow of this script is as follows:
Main is run, so it prints 'Here 3'
change is called, so it prints 'Here 1'
When importing test, python runs the main function of test
When calling change the second time, python is smart enough to know that test is already imported, so it effectively skips that line.
The imported main finishes running
The original script finishes running.
While user2367112's excellent answer explains why this happens, none of the answers here offer a workaround.
There are two easy ways to achieve the desired behavior.
Rather than importing test, use import __main__ instead. If you assign an alias with import __main__ as test, you won't even have to change any other code.
You can set sys.modules['test'] = sys.modules['__main__'] to tell python "Hey, this module already exists". After this, import test will not re-import the module, thus making your code work as expected. The relevant docs on sys.modules can be found here.
Related
I want to set a breakpoint on the set.update() function, but when I try, I get an error message.
Example:
ss= set()
ss.update('a')
Breakpoint:
b set.update
b ss.update
Errors:
The specified object 'ss.update' is not a function
or was not found along sys.path.
The specified object 'set.update' is not a function
or was not found along sys.path.
(Note, I also tried with the parentheses at the end, e.g., b set.update(), but still got the error. I didn't print all the permutations of errors.)
Thanks! Using #avasal's answer and Doug Hellmann's pdb webpage, I came up with this:
Since I was trying to catch set.update, I had to edit the sets.py file, but that wasn't enough, since python was using the builtin set class rather than the one I edited. So I overwrote the builtin sets class:
import sets
locals()['__builtins__'].set=sets.Set
Then I could set conditional break points in the debugger:
b set.update, iterable=='a' #successful
b set.update, iterable=='b' #won't stop for ss.update('a')
My entire example file looks like this:
import pdb
import sets
locals()['__builtins__'].set=sets.Set
pdb.set_trace()
ss = set()
ss.update('a')
print "goodbye cruel world"
Then at the debugger prompt, enter this:
b set.update, iterable=='a'
Hope this helps others too.
I'm trying to access some Fortran subroutines using F2PY, but I've ran into the following problem during consecutive calls from IPython. Take this minimal Fortran code (hope that I didn't code anything stupid; my Fortran is a bit rusty..):
! test.f90
module mod
integer i
contains
subroutine foo
i = i+1
print*,i
end subroutine foo
end module mod
If I compile this using F2PY (f2py3.5 -c -m test test.f90), import it in Python and call it twice:
# run.py
import test
test.mod.foo()
test.mod.foo()
The resulting output is:
$ python run.py
1
2
So on every call of foo(), i is incremented, which is supposed to happen. But between different calls of run.py (either from the command line or IPython interpreter), everything should be "reset", i.e. the printed counter should start from 1 for every call. This happens when calling run.py from the command line, but if I call the script multiple times from IPython, i keeps increasing:
In [1]: run run.py
1
2
In [2]: run run.py
3
4
I know that there are lots of posts showing how to reload imports (using autoreload in IPython, importlib.reload(), ...), but none of them seem to work for this example. Is there a way to force a clean reload/import?
Some side notes: (1) The Fortran code that I'm trying to access is quite large, old and messy, so I'd prefer not to change anything in there; (2) I could easily do test.mod.i = something in between calls, but the real Fortran code is too complex for such solutions; (3) I'd really prefer a solution which I can put in the Python code over e.g. settings (autoreload, ..) which I have to manually put in the IPython interpreter (forget it once and ...)
If you can slightly change your fortran code you may be able to reset without re-import (probably faster too).
The change is about introducing i as a common and resetting it from outside. Your changed fortran code will look this
! test.f90
module mod
common /set1/ i
contains
subroutine foo
common /set1/ i
i = i+1
print*,i
end subroutine foo
end module mod
reset the variable i from python as below:
import test
test.mod.foo()
test.mod.foo()
test.set1.i = 0 #reset here
test.mod.foo()
This should produce the result as follows:
python run.py
1
2
1
I wrote a small program in sample.py file,
a=6
def f1():
a=3
return f2()
#def f2(): commented intentionally
# b = a*a
# return b
and loaded as __main__ module using command
>>>python -i sample.py
But i see that interpreter does not check the binding of f2 during loading of module.
Interpreter only realises that f2 name is not binded to its value when i call
>>>f1()
Another example, where interpreter checks the binding of name big1 , while loading the file as __main__ module using command >>>python -i sample.py throws an error saying big1 is not defined
big, small = 3, -4
while big > 2 or small < -2:
big, small = -small - 1, -big + 1
print(big1)
My question is:
1)
Why python interpreter does not take an effort to check whether all names are bind during loading of sample.py file as __main__ module and defer to using that name f1()?
2) Do you think large projects will create complexity, Because the test cases written must make sure each name is used for testing before it goes for production?
Consider this example:
def f1():
name = raw_input()
exec "def {}(): print 'I am a function'".format(name)
f2()
If a user enters "f2" when prompted, then f2() will execute correctly, but not otherwise.
This is a perfectly legal python program, and the line f2() may or may not execute correctly, dependent completely on user input. So python cannot determine at module load time whether execution of this code will result in a name error or not.
Addressing some additional confusion:
It might seem that python does sometimes do static name-checking. Ie, if we have file1.py:
def foo():
print x1
and you do python file1.py, no error will be printed. The function foo has been defined, but not run. We could also do python -i file1.py, which will open up an interpreter. If in the interpreter we then type foo(), now the code will run, and we'll get the lookup error for x1.
Consider a second file file2.py:
print x1
Here, there is no function being defined. We're simply running a print statement at the top-level. Doing python file2.py will cause a lookup error for x1, since running file2.py constitutes actually running that print statement, as opposed to only defining a function that would run the print statement when called.
So it's not that python sometimes does static name-checking -- python will only throw a name error when code involving that name is actually run. It's just that when code gets run depends on where it is (in a function vs being top-level).
Assume these 3 files:
charNames.py
a = 'Susan'
b = 'Charlie'
c = 'Jiji'
threenames.py
a = 'dead'
b = 'parrot'
c = 'sketch'
print a,b,c
storytime.py
#!/usr/bin/env python
import charNames
import threenames
print charNames.a
threenames
I run storytime.py (which is also chmod +x) by using ./storytime.py from Terminal, this is the output that I get:
$ ./storytime.py
dead parrot sketch
Susan
$
Why does the result execute print a,b,c from threenames.py before it runs print charNames.a?
From my understanding, Python is a top down programming language, like bash. So should it print "Susan" first, then "dead parrot sketch"?
This is run on OSX, with Python 2.7.5
In Python when you import a file it is executed. That is why you are seeing the output from threenames.py first, because it is executed right after it is imported.
If you want a way to only run code in a file if it is the main file and not an import, you can use this code in threenames.py:
if __name__ == '__main__':
print a, b, c
If you run threenames.py, you will see a,b, and c printed because it is the main file, but when it is imported, it is module, so the print function and any other function calls inside that conditional will not be executed
When you import a file, that file is actually executed. So when you import threenames that file is executed, hence you getting output from within that (the print a,b,c) before you think you called output from it.
You need to avoid printing things out in external modules, instead printing the attributes within like you have with charnames.a.
You should instead use a main() function-like structure:
if __name__ == '__main__':
print a, b, c
I want to set a breakpoint on the set.update() function, but when I try, I get an error message.
Example:
ss= set()
ss.update('a')
Breakpoint:
b set.update
b ss.update
Errors:
The specified object 'ss.update' is not a function
or was not found along sys.path.
The specified object 'set.update' is not a function
or was not found along sys.path.
(Note, I also tried with the parentheses at the end, e.g., b set.update(), but still got the error. I didn't print all the permutations of errors.)
Thanks! Using #avasal's answer and Doug Hellmann's pdb webpage, I came up with this:
Since I was trying to catch set.update, I had to edit the sets.py file, but that wasn't enough, since python was using the builtin set class rather than the one I edited. So I overwrote the builtin sets class:
import sets
locals()['__builtins__'].set=sets.Set
Then I could set conditional break points in the debugger:
b set.update, iterable=='a' #successful
b set.update, iterable=='b' #won't stop for ss.update('a')
My entire example file looks like this:
import pdb
import sets
locals()['__builtins__'].set=sets.Set
pdb.set_trace()
ss = set()
ss.update('a')
print "goodbye cruel world"
Then at the debugger prompt, enter this:
b set.update, iterable=='a'
Hope this helps others too.