[Tutor] Puzzled by execfile()

Danny Yoo dyoo at hkn.eecs.berkeley.edu
Thu Oct 21 03:13:47 CEST 2004



On Wed, 20 Oct 2004, [ISO-8859-1] Andr=E9 Roberge wrote:

> Dear Tutors,
>
> I have the following two Python files
>
> =3D=3D=3DScript1.py =3D=3D=3D
> def printfoo():
>     print "foo"
> execfile("Script2.py")
>
> =3D=3D=3DScript2.py=3D=3D=3D
> from Script1 import *
> print "starting"
> printfoo()
> print "done"
> =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D



Hi Andre,

The problem is circularity:  Script1.py uses Script2.py, and Script2 uses
Script1.py!  This is a no-no.  *grin*


Python tries to do something reasonable by keeping track of what modules
have already been imported, and it'll break the circularity at some point
to keep the system from doing a recursive import.


We can sorta simulate this in our heads.  Let's imagine this record as
some list:

    LIST_OF_IMPORTED_MODULES =3D []

Script1: The first time you execute Script1, it gets to the execfile()
statement, and now executes Script2.

    Script2: We now hit the 'from Script1 import *' line.  That's an
    import, and since the LIST_OF_IMPORTED_MODULES is empty, now it'll try
    to import Script1.  Let's mark that.  LIST_OF_IMPORTED_MODULES =3D
    [Script1].  Since this is an import, we'd better import the module.

        Script1: Ok, we're back in Script1.  Ok, we hit the execfile
        again.  Time to execute Script2 again.


            Script2: Ok, we hit the 'from Script1 import *' line again.

            Now if Python had not been keeping track of what modules are
            imported, you can imagine that we'll be doing this cycle
            forever.  Thankfully, we don't.  LIST_OF_IMPORTED_MODULES
            already has Script1, so we don't do the import.

            We go onto the next statements, which accounts for seeing:

            > starting
            > foo
            > done

            ... and now we get out of the execfile.

        ... and now we get out of the Script1 import

    Now that the import is inished, we go onto the next statements, which
    accounts for us seeing:

    > starting
    > foo
    > done

    ... And now we get out of the execfile.

and now we're done.



So that's why we see the output twice when we initially run Script1. But
the second time we execute Script1, we only see the outputs once, because
the LIST_OF_IMPORTED_MODULES lives on in the PythonWin or IDLE
environment.



In summary, don't do that.  *grin* Don't make your programs depend on each
other like that: it makes things REALLY darn confusing.


Instead of having:

###
> =3D=3D=3DScript1.py =3D=3D=3D
> def printfoo():
>     print "foo"
> execfile("Script2.py")
>
> =3D=3D=3DScript2.py=3D=3D=3D
> from Script1 import *
> print "starting"
> printfoo()
> print "done"
###


break the circularity, and just execute Script2.py directly:

###
=3D=3D=3DScript1.py =3D=3D=3D
def printfoo():
    print "foo"


=3D=3D=3DScript2.py=3D=3D=3D
from Script1 import *
print "starting"
printfoo()
print "done"
###


Anyway, hope that make things a little clearer.  Good luck!



More information about the Tutor mailing list