Module executed twice when imported!

M

Michael Abbott

It seems to be an invariant of Python (insofar as Python has invariants)
that a module is executed at most once in a Python session. I have a
rather bizzare example that breaks this invariant: can anyone enlighten
me as to what is going on?

--- test.py ---
import imptest
execfile('subtest.py', dict(__name__ = 'subtest.py'))
--- imptest.py ---
print 'Imptest imported'
--- subtest.py ---
import imptest
---

$ python test.py
Imptest imported
Imptest imported
$

Hmm. If the value __name__ is omitted from the dictionary, or if its
value doesn't match at least 'subtest.' then the message is printed only
once (for example, passing dict(__name__='subtest') produces one
"imported" message).

This happens with both python 2.4 and 2.3. I don't get it.
 
S

Simon Forman

Michael said:
It seems to be an invariant of Python (insofar as Python has invariants)
that a module is executed at most once in a Python session. I have a
rather bizzare example that breaks this invariant: can anyone enlighten
me as to what is going on?

--- test.py ---
import imptest
execfile('subtest.py', dict(__name__ = 'subtest.py'))
--- imptest.py ---
print 'Imptest imported'
--- subtest.py ---
import imptest
---

$ python test.py
Imptest imported
Imptest imported
$

Hmm. If the value __name__ is omitted from the dictionary, or if its
value doesn't match at least 'subtest.' then the message is printed only
once (for example, passing dict(__name__='subtest') produces one
"imported" message).

This happens with both python 2.4 and 2.3. I don't get it.

I don't get it either but there may be a clue in the docs for the
execfile() function
(http://docs.python.org/lib/built-in-funcs.html#l2h-24)

"It is different from the import statement in that it does not use the
module administration --"

I don't know why the globals dict you're passing in would change the
behavior though. Hopefully someone else can enlighten us both.

Peace,
~Simon
 
B

Bruno Desthuilliers

Michael Abbott a écrit :
It seems to be an invariant of Python (insofar as Python has invariants)
that a module is executed at most once in a Python session. I have a
rather bizzare example that breaks this invariant: can anyone enlighten
me as to what is going on?

--- test.py ---
import imptest
execfile('subtest.py', dict(__name__ = 'subtest.py'))
--- imptest.py ---
print 'Imptest imported'
--- subtest.py ---
import imptest
---

$ python test.py
Imptest imported
Imptest imported
$

Hmm. If the value __name__ is omitted from the dictionary, or if its
value doesn't match at least 'subtest.' then the message is printed only
once (for example, passing dict(__name__='subtest') produces one
"imported" message).

During module evaluation, __name__ is usually set to the name of the
module *object*, not the name of the *file*. I suspect that it has
something to do with your observation.
 
M

Michael Abbott

Bump

Michael Abbott said:
--- test.py ---
import imptest
execfile('subtest.py', dict(__name__ = 'subtest.py'))
--- imptest.py ---
print 'Imptest imported'
--- subtest.py ---
import imptest
---

$ python test.py
Imptest imported
Imptest imported
$

I claim this as an unreported (and highly obscure) Python bug.
 
J

John Salerno

Simon said:
I don't get it either but there may be a clue in the docs for the
execfile() function
(http://docs.python.org/lib/built-in-funcs.html#l2h-24)

"It is different from the import statement in that it does not use the
module administration --"

Just after the above statement, it also says:

"it reads the file unconditionally and does not create a new module."

so perhaps that means that it isn't really being imported the second
time, just that the contents are being executed?
 
M

Michael Abbott

(http://docs.python.org/lib/built-in-funcs.html#l2h-24)
"It is different from the import statement in that it does not use the
module administration --"

Just after the above statement, it also says:

"it reads the file unconditionally and does not create a new module."

so perhaps that means that it isn't really being imported the second
time, just that the contents are being executed?[/QUOTE]

Interesting thought.

I'm not convinced, though: firstly, I read that statement as describing
what happens to the file named in the execfile() statement; and
secondly, the problem *only* happens if the global dictionary passed to
execfile() has a '__name__' and if the value of that key is sufficiently
close to the name of the file being passed to execfile().

I found that passing __name__='whatever' resulted in normal import
behaviour, and so does __name__='subtest', but curiously enough passing
__name__='subtest.' results in the double import.
 
P

Peter Maas

Michael said:
I claim this as an unreported (and highly obscure) Python bug.

The docs tell us
(http://www.python.org/doc/2.4.2/lib/built-in-funcs.html):

------------------------- begin -------------------------------
execfile(filename[, globals[, locals]])

This function is similar to the exec statement, but parses a file
instead of a string. It is different from the import statement in that
it does not use the module administration -- it reads the file
unconditionally and does not create a new module.
------------------------- end ---------------------------------

I claim this as a well documented (and thus exspectable) Python behaviour.
execfile() just executes a file unconditionally without searching in
sys.modules. That's its purpose, otherwise it would be a synonym of
the import statement.

Peter Maas, Aachen
 
G

Georg Brandl

Michael said:
Just after the above statement, it also says:

"it reads the file unconditionally and does not create a new module."

so perhaps that means that it isn't really being imported the second
time, just that the contents are being executed?

Interesting thought.

I'm not convinced, though: firstly, I read that statement as describing
what happens to the file named in the execfile() statement; and
secondly, the problem *only* happens if the global dictionary passed to
execfile() has a '__name__' and if the value of that key is sufficiently
close to the name of the file being passed to execfile().

I found that passing __name__='whatever' resulted in normal import
behaviour, and so does __name__='subtest', but curiously enough passing
__name__='subtest.' results in the double import.[/QUOTE]

That's because __name__ is normally set to the module's name in the package
hierarchy. When you set it to "some1.some2", Python thinks it's
in a subpackage and when it does "import imptest" Python searches for
the module "some1.imptest", not for "imptest", and finds it in the
current directory (which it assumes to be the package directory).

You can verify this by inspecting sys.modules after the execfile() call.

So it's not a bug, but expected behavior.

Georg
 
G

Georg Brandl

Peter said:
The docs tell us
(http://www.python.org/doc/2.4.2/lib/built-in-funcs.html):

------------------------- begin -------------------------------
execfile(filename[, globals[, locals]])

This function is similar to the exec statement, but parses a file
instead of a string. It is different from the import statement in that
it does not use the module administration -- it reads the file
unconditionally and does not create a new module.
------------------------- end ---------------------------------

I claim this as a well documented (and thus exspectable) Python behaviour.
execfile() just executes a file unconditionally without searching in
sys.modules. That's its purpose, otherwise it would be a synonym of
the import statement.

This has nothing directly to do with the "problem" since the seemingly
double imported module is not the one that's execfile'd.

Georg
 
M

Michael Abbott

That's because __name__ is normally set to the module's name in the package
hierarchy. When you set it to "some1.some2", Python thinks it's
in a subpackage

Ahhhh.

So what I *should* have set it to is the module name *without*
extension, i.e. __name__='imptest'

Thank you. Now I think I understand it.
 
G

Georg Brandl

Michael said:
Ahhhh.

So what I *should* have set it to is the module name *without*
extension, i.e. __name__='imptest'

Thank you. Now I think I understand it.

You're welcome. This is indeed not easy to look through.

Georg
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,733
Messages
2,569,440
Members
44,830
Latest member
ZADIva7383

Latest Threads

Top