[Python-ideas] Replacing the if __name__ == "__main__" idiom (was Re: making a module callable)
INADA Naoki
songofacandy at gmail.com
Mon Nov 25 04:08:04 CET 2013
I want to have callable main function to allow script can be executed
directly or from other function.
def main():
<blah>
if is_main():
main()
is not shorter than
@mainfunction
def main():
<blah>
But I like:
def __main__():
<blah>
On Mon, Nov 25, 2013 at 8:11 AM, Guido van Rossum <guido at python.org> wrote:
> 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)
>
> _______________________________________________
> Python-ideas mailing list
> Python-ideas at python.org
> https://mail.python.org/mailman/listinfo/python-ideas
>
>
--
INADA Naoki <songofacandy at gmail.com>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-ideas/attachments/20131125/4146749b/attachment.html>
More information about the Python-ideas
mailing list