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


On 25 Nov 2013 07:26, "Antoine Pitrou" <solipsis@pitrou.net> wrote:
>
> On Sun, 24 Nov 2013 11:10:43 -0800
> Guido van Rossum <guido@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)