main function¶
a module-level function named main is the program entry point. basedpython
appends a __main__ guard that invokes it, so running the file as a script
executes main:
transpiles to:
async¶
an async def main is driven through asyncio.run, and the import is added
for you:
command-line arguments¶
main's parameters are the program's command-line interface. each one can be
given positionally, in declaration order, or by name:
a parameter with a default is optional; one without is required. an underscore
in a name is also spelled with a dash on the command line, and both forms are
accepted (--out-dir and --out_dir). the docstring of main becomes the
--help description:
from pathlib import Path
def main(name: str, count: int = 1, out_dir: Path = Path("."), verbose: bool = False):
"""greet someone repeatedly"""
types¶
a parameter is exposed on the command line when its annotation is one of
str, int, float, bool, or Path. the annotation is used as the
converter, so a bad value is reported before main runs:
bool is a flag rather than a value: --verbose sets it True and
--no-verbose sets it False. a flag takes no positional slot, so the value
tokens on the command line still line up with the remaining parameters. a
bool without a default is required, meaning one of the two flags must be
given.
a parameter with any other annotation is not exposed. if it has a default it
simply keeps that default; if it is required, main cannot be called from the
command line at all and is left alone — the module gets no entry-point guard.
*args / **kwargs are never exposed, and never block the guard.
positional-only and keyword-only parameters keep their calling convention: a
positional-only parameter is still passed positionally to main even when the
command line named it with --, and a keyword-only one never takes a
positional slot.
the project entry point¶
main makes a module runnable; run.main says which module that is for the
project as a whole:
by run with no module then runs app.cli. see the
cli reference
scope¶
only a top-level function named main is recognized — a main method on a
class is just a method. when several top-level main definitions exist, the
last one wins, matching the binding main resolves to at runtime.
the guard is suppressed in three cases:
- the module already invokes
mainitself, either through a hand-writtenif __name__ == "__main__":guard or a bare top-levelmain()call. the entry point is never run twice mainis markedprivate(it is renamed and is not a public entry point)mainhas a required parameter the command line can't supply, so calling it would raiseTypeError
completion¶
at module level, completing main writes the whole definition rather than the
name — there is only one thing a top-level main can be. once the module has
one, the name completes to it like any other
why¶
most scripts end with the same boilerplate guard. naming the entry point
main and letting basedpython emit the guard keeps the source focused on the
program itself, the way a compiled language treats its main