Python Script Template

Published on Sept. 16, 2023 | Tags: Python shell aliases

I often found myself writing the same basic script whenever I needed to start writing a small script for testing something or for writing a fully fledged program. And, of course, writing the same thing over and over again it gets tedious and boring. At some point, I figured it would be great to have a command that I can invoke and copy, from a template, this base.


Without further ado, here is the basic script template I use for almost anything python:


#! /usr/bin/env python
from __future__ import annotations
import argparse
from typing import Sequence

def main(argv: Sequence[str] | None = None) -> int:
parser = argparse.ArgumentParser()
parsed_args = parser.parse_args(argv)
print(parsed_args)
return 0

if __name__ == "__main__":
raise SystemExit(main())


[source]


This template is based from this video from Anthony.


However, this is just sitting in a directory in my configuration files repo. The magic comes from this shell function:


function vt() {
local FILENAME
FILENAME=${1:-"t.py"}
cp -p $DOTFILES/python/templates/main.py "$FILENAME"
"$EDITOR" "$FILENAME"
}

[source]


Which, will allow you to copy the template to the current directory under a specified name or t.py by default.


Of course, as mentioned in the video, this script is very testable, so naturally, I wrote a couple of tests for it:


import pytest
from python.templates import main

def test_main_no_args(capsys):
code = main.main([])
out, err = capsys.readouterr()
assert code == 0
assert out == "Namespace()\n"
assert err == ""

def test_main_arg_help(capsys):
with pytest.raises(SystemExit) as exc:
main.main(["-h"])
out, err = capsys.readouterr()
assert exc.value.code == 0
assert (
out
== "usage: __main__.py [-h]\n\noptions:\n -h, --help show this help message and exit\n"
)
assert err == ""

def test_main_unrecognized_argument(capsys):
with pytest.raises(SystemExit) as exc:
main.main(["nonsense"])
out, err = capsys.readouterr()
assert exc.value.code == 2
assert out == ""
assert err == (
"usage: __main__.py [-h]\n__main__.py: error: unrecognized arguments: nonsense\n"
)


[source]


And this has become really useful for quickly creating small standalone scripts and allow you to focus on the important part of the script, with the added benefit of having a nice CLI interface with argparse.


Ferran Jovell