On Fri, Oct 01, 2021 at 03:35:26PM -0400, Jonathan Crall wrote:
> My motivation for writing this suggestion is in an attempt to stop a common
> anti-pattern, where instead of defining a `main` function (or a function by
> any other name) an simply calling that by adding the above two lines, a lot
> of Python users I work with will just start dumping their logic into the
> global scope of the module.
>
> Needless to say, this can have consequences.
What sort of consequences are you thinking of, under what circumstances?
Remember, Python is first and foremost a scripting language. There's
nothing wrong with writing scripts that run in the global scope.
> If there was some default
> builtin, let's call it `__main__` for now (open to suggestions), that took
> a function as an argument and conditionally executed it if `__name__ ==
> "__main__"` in the caller's scope, that would allow us to simplify the
> above boilerplate to a single line with no extra indentation:
>
> ```
> def main():
> ...
>
> __main__(main)
> ```
You don't need `__main__` to be built into the interpreter. It's a
two-line pattern: not every two line function needs to be a builtin.
```
def __main__(func):
if __name__ == '__main__': func()
```
Put that in a module, then:
```
from module import __main__
```
in all your scripts.
If you're worried about keystrokes, and your editor doesn't have a
"snippets" functionality, you can put your `__main__` in your
PYTHONSTARTUP file or sitecustomize.py and have it loaded automatically
into builtins.
https://pymotw.com/3/site/
```
import builtins
builtins.__main__ = __main__
```
> In addition to being simpler, it would allow users to avoid the trap of
> adding logic that impacts the global scope.
There is nothing necessarily wrong with logic that impacts the global
scope in a script. It can be the easiest thing that works. The more
complex your system, the more there is to go wrong.
Is your definition of simpler based on counting keystrokes? The
underlying complexity is the same. Your builtin `__main__` performs
exactly the same conditional test, it's just buried behind a function
call.
> Furthermore, it could be used as a decorator (and the use-case wouldn't be
> unreasonable!), and we all know how much new Python users love decorators
> when they find out about them.
Are you being sarcastic? The idiom "We all know how much X love Y" is
typically (but not always) used sarcastically.
Decorator syntax has been a great success for Python, but even to this
day newbies often struggle to understand them and even some experienced
users avoid them.
My completely unscientific, pluck-a-figure-out-of-the-air guestimate is
that about 10% of Python users treat decorators as a hammer and every
problem they see as a nail, another 10% find them to be utterly
perplexing and a source of dread, 20% know how to cut-and-paste a recipe
involving decorators when needed, but don't know how they work (and have
no interest in learning), and the rest have some reasonable level of
understanding of how to use decorators and write their own.
In this particular case, using decorator syntax:
@__main__
def main(): ...
to call the function immediately, rather than the more straightforward
__main__(main)
seems to me to fall squarely in the "hammer + nail" category. I can't
tell whether this is a serious proposal on your part or not.
> Maybe having such a builtin would discourage globals and help new users get
> the use-decorators-everywhere bug out of their system.
There is no need to discourage globals for script writing. And I'm not
entirely sure how it follows that encouraging people to use a decorator
to run their script main function will discourage them from using
decorators everywhere. What have I misunderstood?
--
Steve
_______________________________________________
Python-ideas mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at
https://mail.python.org/archives/list/[email protected]/message/YSCULW6535SKXEGCYM7AQDOHINSUWRA3/
Code of Conduct: http://python.org/psf/codeofconduct/