Your argparse is not the interface of your application
This is another post in the series lessons learned building machine learning systems.
Your argparse should not be the interface of your application. Instead, your argparse should be a specific implementation of it.
Consider the following example. I used to always structure my code like this
import argparse
import sys
if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument("--foo", type=int)
args, _ = parser.parse_known_args(sys.argv[1:])
foo = args.foo
result = foo + 1
Instead what we should do is this
def run(args: argparse.Namespace):
foo = args.foo
result = foo + 1
if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument("--foo", type=int)
args, _ = parser.parse_known_args(sys.argv[1:])
run(args)
The difference is that the argparse becomes a specific implementation of the actual interface, which is the run
function.
Before: No separation between interface (the argparse) and implementation (also the argparse).
After: Clear separation between interface (run
function) and implementation (argparse).
This separation makes our code easier to test.
We now can write another testing implementation just using the run
function instead of having to rely on the argparse to test the full flow of the application.
In this trivial example it almost seems obvious, but for some reason I did manage to completely forgot this in a larger and more complex codebase.
The solution is simple, just wrap whatever is happening in your __main__
into a single function called run
:)
Comments