[Python-ideas] Replacing the if __name__ == "__main__" idiom (was Re: making a module callable)

Guido van Rossum guido at python.org
Mon Nov 25 00:11:04 CET 2013


On Sun, Nov 24, 2013 at 2:21 PM, Nick Coghlan <ncoghlan at gmail.com> wrote:

>
> On 25 Nov 2013 07:26, "Antoine Pitrou" <solipsis at pitrou.net> wrote:
> >
> > On Sun, 24 Nov 2013 11:10:43 -0800
> > Guido van Rossum <guido at python.org> wrote:
> > > Haven't followed all of this, but perhaps the simplest thing would be
> to
> > > define a new builtin function that returns True in the namespace of the
> > > main module and false everywhere else. It could be implemented by
> pulling
> > > '__name__' out of the caller's local namespace and comparing it to
> > > '__main__'. We could name this function __main__(), or perhaps less
> > > dramatic, is_main(). Then you could write
> > >
> > > if is_main():
> > >     <do your main code>
> >
> > Why not make it so that a module function named __main__, if it exists,
> > gets executed when the module is run as a script?
>
> I consider the fact that the semantics of __main__ execution are largely
> the same as those of any other module import to be a feature rather than a
> bug.
>
Right!

> Keep in mind that we *can't* stop the current idiom from working (since we
> have to run the top level code to build the module in the first place), and
> that "run this script from disk" is just one way of executing __main__. For
> example, the REPL loop is a statement-by-statement interactive rendition of
> __main__, while __main__.py files in zipfiles, directories and packages
> don't bother with the "if __name__ == '__main__'" guard at all.
>
> Any "define a function with this special name" idiom would require making
> a decision on what it means in the REPL (implicit atexit() function?
> Automatically called when declared?), and changes not only to pythonrun.c,
> but also to runpy, IDLE, and various other IDE's. pdb, profile, coverage
> tools, etc would also all need to  change (unless this was made an implicit
> feature of exec() and execfile(), which really doesn't sound like a good
> idea).
>
> Whether or not runpy's module API should trigger __main__ function
> execution becomes a tricky question, as does the fact that many of the
> PyRun_* helpers execute code in the __main__ namespace. Should they trigger
> execution of special __main__ functions as well?
>

I'm not sure that the REPL behavior w.r.t. such a special function should
be the deciding factor.

> I don't have good answers to many of those questions, which is why I think
> the whole idea of introducing "main functions" to Python as anything more
> than a conventional idiom isn't worth the hassle. I consider the desire for
> such a feature just a relic of people's experience with languages like C
> and Java where the top level module code is just a declaration of program
> structure to the compiler rather than a full fledged execution environment.
>
> (Another point of confusion: C etc will complain if multiple main function
> declarations are linked into the same program, while Python would silently
> ignore any that weren't in the main module).
>
I think that explicit is better than implicit, and that's where a special
function name loses. Also, there's no reasonable way to backport a special
function. (Whereas backporting is_main() is trivial, since the behavior of
sys._getframe() is past releases is stable.)

A decorator is perhaps a little better, but it immediately brings up the
question of when the decorated function should be called, if this *is* the
main module. There are two options: after the import is complete (matching
how a special function name would work) or at the point where the decorated
function occurs. If we want people to be able to backport the decorator it
would have to be the latter.

But the decorator is more verbose than even the current idiom:

@mainfunction
def main():
   <blah>

vs.

if __name__ == '__main__':
    <blah>

whereas my proposal is shorter *and* more readable:

if is_main():
    <blah>

>  > (this would also mimick the __main__.py convention for packages)
>
> Not really - that's still just normal script execution, and it has a
> couple of very clear triggers analogous to the "if __name__ == '__main__'"
> idiom for ordinary scripts (the import system indicating the specified name
> refers to a package rather than a simple module for module execution, or to
> a valid sys.path entry for direct execution).
>
> Since those modules don't include the idiomatic guard, running them
> directly in IDLE (or elsewhere) will still typically do the right thing.
>
> I don't mind Guido's idea of an "is_main()" builtin for 3.5, though. It
> should be less confusing for beginners, and for those that subsequently
> want to understand the details, it can be explained in terms of the
> existing, more explicit idiom. But trying to level shift from "the main
> module is special" to "the already special main module may optionally
> declare a special main function"? That's *way* more complicated than many
> folks seem to realise.
>
Yup.

-- 
--Guido van Rossum (python.org/~guido)
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-ideas/attachments/20131124/1a98fb7a/attachment.html>


More information about the Python-ideas mailing list