Parsing arguments in Python isn’t hard. There are already many libraries for command line argument parsing in Python, not least
argparse in the standard library. However, just because it’s not hard doesn’t mean it’s entirely without effort, and when you’re working on specific problem it’s probably not top of your mind. Creating a proper command line syntax for your quick script or runnable module requires making declarations or tagging things, so you just end up writing something like this and moving on:
if __name__ == '__main__': infile, outfile = sys.argv[1:] do_stuff(infile, outfile)
It’s rough, but it gets the job done. However, throw away scripts have a tendency not to get thrown away, and this kind of overly spartan, undocumented CLI can end up hanging around for longer than first thought. Adding features is a pain, and a rewrite using a more structured framework is a lot of effort and has to maintain compatibility with the ad hoc version.
Quarg was written to address this problem directly, allowing a proper command line interface to be built up incrementally, starting from nothing. The first and most important design goal was that it worked on unmodified Python code, and produced sensible results. This is done by taking the information that’s already there — top level functions, parameters names, and docstrings — and building an interface based on some broad assumptions and conventions.
The purely automatic interface (which you can get by running your script with
quarg as the interpreter, or adding a call to
quarg.main() at the end) is useful, and often sufficient, but you can refine it by adding annotations in the form of function decorators and specially formatted docstrings. This is what allows and interface to be built incrementally, rather than requiring a fixed amount of effort up front.
Under the hood, the actual argument parsing is done with
argparse, and much of the functionality of that library is available via the
arg decorator. While there are fancier libraries out there, I’ve always found the parsing of
argparse to be good enough, and it avoids adding an external dependency. Quarg only depends on the standard library, and works in Python 2 and 3, so it should be easy to integrate into most contexts. It’s available on PyPI (
pip install quarg).
(On a personal note, I’ve been using Python for 18 years, and while that’s mostly been ad hoc and proprietary stuff, I’ve shared numerous projects on GitHub (and, earlier, SourceForge). However, this is the first package I’ve uploaded to PyPI. The process was pretty straightforward and painless thanks to the Python Packaging User Guide, and I’ll definitely be doing it again. The spread of unified package indices such as PyPI, NPM and CPAN are one of the biggest practical improvements to the programming experience that I’ve seen over the last two decades, and it’s taken me too long to pitch in.)
There are numerous ways in which Quarg could be improved — for example, by making use of type annotations if they’re present. There are also no doubt numerous bugs still to be fixed. Nevertheless, we’ve been using it internally at Cydar for a while now, and found it pretty useful. Hopefully you will too.
While I’m the main author and maintainer of the library, Quarg began life at Cydar, and the company retains the copyright. Thanks to my colleagues at Cydar, particularly Ian Glover, for useful feedback and code contributions. Unfortunately the latter are not attributed in the Git history, as I had to excise it from a larger private repository.