Callable Types and Custom Actions
00:00 In the previous lesson, I showed you a mix of less common parser features. In this lesson, I’ll show you some advanced parsing mechanisms.
You’ve used the
type parameter to convert the command line string argument into an integer. You can also do this with the
In fact, you can use any callable. Whatever the user gives you gets sent as the parameter to the callable. This gives some interesting possibilities. You could use the
ord function to get the ASCII value or Unicode code point of a character.
You could directly use the
open function to open the given file name. Or you could create a
Path object in order to manipulate files.
But don’t go crazy. Some things are better to be handled in your code rather than as side effects to your argument parser. For example, the reason the
store_true action exists instead of just using the
bool callable is because
bool treats empty strings as false and non-empty strings as true.
So your string containing
0 will not give the value you might have expected. That
open I mentioned earlier, it just feels icky to me. And that could only get worse, if you start using a file decoder of some sort. It will work, but the errors start to become opaque.
01:23 The user won’t be able to see the difference between a bad value for the argument and a good value that points to a file with bad contents. Generally, I recommend sticking to the more common cases and avoiding getting too fancy.
This is both because you have to be careful with corner cases and also for the readability of your code. Another developer coming along might not expect the namespace to contain an
open file, let alone a fully parsed one.
Title pretty much says it all. You can write your own storage actions. You do that by inheriting from
argparse.Action. Let me show you how.
Before showing you how to write your own, I’m going to show you something slightly simpler, using the built-in
action class that doesn’t correspond to an
action string name. Instead of giving something like
store_true, you can give any class that inherits from
argparse library comes with one of these called
BooleanOptionalAction. This one works kind of like
store_true, but allows you to use a
--no version of the flag.
I’ll show you what that looks like in a second. The other thing I’ve done in this line is to use the
dest parameter. This parameter allows you to specify what the name of the variable in the namespace is. Since
try is a keyword in Python, if I attempted to use it as is, I’d get a
But using the
dest parameter, I can specify that the namespace store
Try with a capital T, which is allowed by the compiler. Let’s try this out. Get it?
02:59 See what I did there? Please tell me I’m clever. I need your approval.
--try flag. Pretty much what you’d expect. Now for the difference …
BooleanOptionalAction class supports the use of
--no in a flag to turn something off. When nine-hundred years old you reach, look as good you will not.
All right, let’s write a custom action now. To do so, you need to inherit from
argparse.Action. The initializer is rather specific. Make sure you get all the parameters correct.
My action is going to add
"Bork, bork, bork!" to the string being stored. As such, I don’t want to handle multiple arguments. Single items only. On lines 6 and 7, I make sure that
nargs isn’t set.
With that check out of the way, I call
super() and let the parent class handle everything else. Now for the meat. The
.__call__() method is what gets called to store the argument.
Your method must use these same arguments or it won’t work. What you get passed in is the
parser instance, the namespace you’re modifying, the values from the command line, and any option strings. On line 12, I take whatever values I was given and add
"Bork, bork, bork!" to the end.
And then on line 13, I do what all actions should do: store the value in the namespace. Scroll on down. To use the custom action, you need to set the
action parameter at your class.
04:41 Note that it’s at the class, not at an instance object. Let’s try this out.
04:56 My script only takes a single argument, so to give it something with spaces in it, I need to surround it with quotes. The operating system uses space to distinguish between arguments sent to the script. By putting it in quotes, my entire sentence from Gonzo is considered as a single argument.
05:13 The sentence is then passed into the borkifying action and is stored with the desired suffix. Hurdy gurdy hurdy gurdy.
05:25 In the next lesson, I’ll show you how to build sub-parsers so that you can write scripts that take subcommands, similar to how Git does.
Become a Member to join the conversation.