[Python-Dev] -z, -i and -m, maybe bug in runpy?
ncoghlan at gmail.com
Tue Jul 24 16:16:24 CEST 2007
Nick Coghlan wrote:
> Phillip J. Eby wrote:
>> While trying to get my -z replacement patch to work, I stumbled across
>> a bug in the -m implementation (and in runpy). It seems that when you
>> run the code of a -m module, it is *not* run in the __main__ module
>> So even though __name__=='__main__', globals() is not
>> sys.modules['__main__'].__dict__. This seems wrong to me. Does
>> anybody know why runpy doesn't actually run the code in the target
> After implementing the runpy explicit relative import tests over the
> last couple of days, it actually occurred to me earlier today that I
> didn't have a test for this scenario. When I thought of the test, I was
> also pretty sure it would fail - it appears I was right :)
OK, I've now had a closer look, and the problem isn't what I initially
thought when I read your message (the test which I expected to fail
actually passed without changing the current implementation). It turns
out that while the module is actually executing it does the right thing
- the problem only arises when the run_module function attempts to clean
up after itself by reverting some of the changes it makes to the sys module.
The specific problem is this sentence from the run_module docs:
"Both sys.argv and sys.modules[__name__] are restored to their
original values before the function returns."
It looks like those semantics are a mistake - the changes to the sys
module should persist after the function terminates, leaving it to the
calling code to decide whether or not it wants to restore the original
>> One consequence of this is that the -i option is much less useful when
>> you use -m, because the script's globals have disappeared before you
>> get to the interpreter prompt.
See above - the problem is that the function is cleaning up after itself
and deleting things that may still be of interest when -i is also specified.
>> At this point, I've successfully gotten a -z replacement patch, except
>> that it inherits this apparent bug from -m, which for a while led me
>> to believe my patch was broken (when in fact it works fine, apart from
>> inheriting the -m behavior).
>> Does anybody know if this behavior is intended, and if so, why? And
>> what are the consequences of changing/fixing it?
It was intended enough to be documented that way, but I don't recall
putting any significant thought into that aspect of the implementation,
and nor do I remember anyone else questioning it.
The fact that it completely breaks the -i switch seems more than enough
reason to consider it a bug, though.
I've changed the behaviour in r56520 to simply leave the alterations to
sys in place when the function terminates. While this is a definite
change to the interface (and hence not a candidate for direct
backporting), I think the difference is small enough for the 2.5 to 2.6
If enough people prefer, I can switch the code to an approach which
fixes -m while leaving the semantics of runpy.run_module alone. This
would involve renaming the version of run_module I just checked into SVN
have -m invoke that version directly. run_module would be changed to
wrap the function used by -m in the necessary code to restore the sys
module to something more closely resembling its original state. That
would also be the approach to take if we decided we wanted to backport
this fix to the 2.5 maintenance branch.
Nick Coghlan | ncoghlan at gmail.com | Brisbane, Australia
More information about the Python-Dev