[Python-ideas] PEP-499: "python -m foo" should bind to both "__main__" and "foo" in sys.modules

Cameron Simpson cs at zip.com.au
Mon Aug 10 12:13:02 CEST 2015


On 08Aug2015 22:12, Andrew Barnert <abarnert at yahoo.com> wrote:
>On Aug 8, 2015, at 16:18, Cameron Simpson <cs at zip.com.au> wrote:
>> I think I take the line that as of PEP 451 the conanical name for a module is .__spec__.name. The module's .__name__ normally matches that, but obviously in the case of "python -m" it does not.
>>
>> As you point out, suddenly a module can appear somewhere other than sys.modules['__main__'] where that difference shows.
>>
>> Let's ask the associated question: who introspects module.__name__ and expects it to be the cononical name? For what purpose?
>
>I'd think the first place to look is code that deals directly with module objects and/or sys.modules--graphical debuggers, plugin frameworks, bridges (a la AppScript or PyObjC), etc. Especially since many of them want to retain compatibility with 3.3, if not 3.2, and to share as much code as possible with a 2.x version
>
>Of course you're probably right that there aren't too many such things, and they're also presumably written by people who know what they're doing and wouldn't have too much trouble adapting them for 3.6+ if needed.

One might hope. So I've started with the stdlib in two passes: looking for 
.__name__ associated with "mod", and looking for __main__ not in the standard 
boilerplate (__name__ == '__main__').

Obviously all this code is unfamiliar to me so anyone with deeper understanding 
who wants to look is most welcome.

Pass 1 with this command:

  find . -type f -name \*.py | xargs fgrep .__name__ /dev/null | grep mod

to look for module related code using .__name__. Of course a lot of it is 
reporting, but there are some interesting relevant bits.

doctest:

This refers to module.__name__ quite a lot. The _normalize_module() function 
uses __name__ instead of __spec__.name. _from_module() tests is an object is 
defined in a particular module based on __name__; I'm (naively) surprised that 
this can't use "is", but it looks like an object's __module__ attribute is a 
string, which I imagine avoids circular references. _get_test() uses __name__ 
instead of __spec__.name, though only as a fallback if there is no __file__.  
SkipDocTestCase.shortDescription() uses __name__.

importlib: mostly seems fine according to my shallow understanding?

inspect: getmodule() seems correct (uses __name__ but seems correctish) - this 
does seem to be a grope around in the available places looking for a match 
function, and feels unreliable anyway.

modulefinder: this does look like it could use __spec__.name more widely, or as 
an adjunct to __name__. scan_code() looks like another "grope around" function 
trying to infer structure from the pieces sitting about:-)

pdb: Pdb.do_whatis definitely reports using .__name__. Not necessarily 
incorrect.

pkgutils: get_loader() uses .__name__, probably ougtht to be __spec__.name

pydoc: also probably should upgrade to .__spec__.name

unittest: TestLoader.discover seems to rely on __name__ instead of 
__spec__.name while constructing a pathname; definitely seems like it needs 
updating for PEP 451. It also looks up __name__ in sys.builtin_module_names to 
reject constructing a pathname.

Pass 2 with this command:

  find . -type f -name \*.py |xxargs fgrep __main__ | grep -v 'if  *__name__  *==  *["'\'']__main__'

looking for __main__ but discarding the boilerplate.

I'm actually striking out here. Since this PEP doesn't change __name__ == 
'__main__' I've not found anything here that looks like it would stop working.  
Even runpy, surcory though my look at it is, is going forward: setting __name__ 
to '__main__' instead of working backwards.

Further thoughts?

Cheers,
Cameron Simpson <cs at zip.com.au>


More information about the Python-ideas mailing list