Wandering Thoughts archives

2016-03-30

I've now used Python's argparse module and I like it

The argparse module is the Python 2.7+ replacement for the old optparse module, which itself was basically an extension of the basic getopt module. A number of years ago, when I could barely start using argparse, I took a look at argparse's documentation and wound up with rather negative feelings about it. Having now written a program or two that uses argparse, I'm going to take those old views back.

I don't yet have any opinion on argparse as more than an optparse replacement for putting together quick argument handling for simple commands, but there are a number of things that I like about it for that role. In no particular order:

  • argparse doesn't produce warnings from pychecker. I know, this is a petty thing, but it's still nice to be able to just run 'pychecker program.py' without having to carefully guard 'import optparse' with various magic bits of code.

  • It's nice to be able to skip setting a default value for boolean flags with a store_true or store_false action. One less bit of code noise.

  • argparse gives you a simple way to define conflicting options. It isn't all that general but just having it there means that my programs have somewhat better option error checking. If I had to do it by hand, I might be tempted to not bother.

    (Because of the lack of generality, argparse doesn't give you top notch handling of conflicting arguments; if you want to do a really good job in even moderately complicated situations, you'll have to at least partially roll your own. But argparse is good enough for handling obvious cases in a simple program that you don't expect to be misused except by accident.)

  • It's conveniently lazy to let argparse handle positional arguments too. You can just tell it that there must be exactly N, or at least one, or whatever, and then continue onwards knowing that argparser will take care of all of the error checking and problem reporting and so on. If it gets to your code, you have at least the right number of arguments and you can pull them off the Namespace object it returns.

    (If you want to go a little bit crazy you can do a bunch of argument type validation as argparse processes the arguments. I'm not convinced that this is worth it for simple programs.)

The result of all of this is to reduce the amount of more or less boilerplate code that a simple argparse-using program needs to contain. Today I wrote one where the main function reduced down to:

def main():
   p = setup_args()
   opts = p.parse_args()
   for grname in opts.group:
      process(grname, opts)

All of the 'must have at least one positional argument' and 'some options obviously conflict' and so on error handling was entirely done for me in the depths of parse_args, so my code here didn't even have to think about it.

(I've historically shoved all of the argument parser setup off into a separate function. It's sufficiently verbose that I prefer to keep it out of the way of the actual logic in my main() function; otherwise it can be too hard to see the logic forest for the argument setup trees. With a separate setup_args() function, I can just skip over it entirely when reading the code later.)

python/ArgparseBriefPraise written at 23:41:54; Add Comment

My view of Debian's behavior on package upgrades with new dependencies

In the primary Reddit discussion of my entry about actually learning apt and dpkg, yentity asked an entirely sensible question:

Why is this [apt-get's --with-new-pkgs] not enabled by default in debian / ubuntu ?

The ultimate answer here is 'because Debian has made a philosophical choice'. Specifically, Debian has decided that no matter what the person building the new version of a Debian package wants or feels is necessary, an 'apt-get upgrade' will never add additional packages to your system. If the builder of the package insists that a new version requires an additional package to be installed, it is better for the upgrade to not happen. Only 'apt-get install <pkg>' (or 'apt-get dist-upgrade') will ever add new packages to your system.

Regardless of what you think about its merits, this is a coherent position for Debian to take. In an anarchic packaging environment with individual Debian developers going their own way, it even has a fair amount of appeal. It certainly means that package maintainers have a strong pragmatic incentive not to add new dependencies, which probably serves to minimize it (which is one reason Debian has apt-get behave this way).

My personal view is that I prefer an environment where package builders are trusted to do the right thing with package dependencies in new versions of their packages, whatever that is. Packages can get new dependencies for all sorts of good reasons, including that what used to be a single package is being split up into several ones. As a sysadmin outsider, I'm not in a good position to second guess the package maintainer on what dependencies are right and whether or not a new one is harmful to my system, so in a trustworthy environment I'll just auto-install new dependencies (as we now do on Ubuntu where it's possible).

(The Debian package format has also made some structural decisions that make things like splitting packages more of a pain. In an RPM-based system, other packages often don't notice or care if you split yours up; in a Debian one, they're more likely to notice.)

It's worth pointing out that this trust fundamentally requires work and politics, in that it requires a policy on 'no unneeded dependencies' (and 'no surprises in package upgrades') and then a group of people who are empowered to judge and enforce the policy (overriding package maintainers when necessary). This sort of control probably does not go well with a relatively anarchic project and it's certainly a point of argument (and one could say that Debian already has enough of those).

linux/DebianUpgradesAndNewPackages written at 01:03:47; Add Comment


Page tools: See As Normal.
Search:
Login: Password:
Atom Syndication: Recent Pages, Recent Comments.

This dinky wiki is brought to you by the Insane Hackers Guild, Python sub-branch.