getopt
00:00
In this lesson, I’ll show you how you can use getopt
from the Python standard library to implement a version of this seq
utility.
00:10
So here, I have a partially completed version of a seq()
implementation using the getopt
module. So of course, I have to import getopt
here, but you’ll notice that this USAGE
message, the VERSION
message, and then this actual seq()
code here are very similar to previous implementations that you’ve seen. seq()
just takes in a list of integer operands and then a separator with a default of a newline, and then it decides what to do based on how many arguments there are. Now, the meat of this code will be in the parse()
function, which I’ll be writing out in a second. But if you take a look at main()
, you’ll see that main()
gets the arguments from sys.argv
, raises a SystemExit
if there are no arguments—because seq
doesn’t function with no arguments—and then it gets the separator and the operands from this parse()
function, which is where all of the logic of getopt
will need to go.
01:03
Then, it just prints out the seq()
of those operands and that separator. So, a lot of this code is very familiar, but this parse()
function will look a little bit different than previous implementations you’ve seen.
01:16
The first thing that you need to do here is to use the getopt.getopt()
function to get the options and the arguments from your actual string list of arguments
01:30
that are passed in from the command line. So, what you can do to do that is say getopt.getopt()
, and then you pass in these string args
, and then you need to pass in a string, which contains all of the short options in just one big concatenated string.
01:50
And this colon at the end indicates that the option preceeding it takes in an option-argument. So this is --version
, which has no option-argument, --help
, which has no option-argument, and then --separator
, which does in fact have an actual option-argument that it takes.
02:05
Then, you need to add in a list of strings here, which are the long forms of those short-form operands that I just showed you. So "separator"
, and then you put an equals here for the one that requires an option-argument.
02:21
So, this will actually get you the options and the arguments in a pretty convenient form, and it will allow you to perform all of your own logic on the options and the arguments. So this is what I mean when I say that getopt
is a little bit more of a manual configuration option than something like argparse
, because what you’re going to have to do is use what getopt
gives you to actually define the logic of your program. So for example, what I can do here is I can say for opt, opt_arg in options
—
02:54
I’ll need to actually define this conditional logic, I’ll need to say if opt in
"-v"
or "--version"
—
03:06
and I actually need to include the double hyphens in front of "version"
, as well—so, if the opt
is in those, then I’m used to print out VERSION
, and then I’ll just sys.exit()
with 0
exit code to show that something worked.
03:22
And then I can also say if opt in
"-h"
or "--help"
,
03:31
then I’ll do the same thing, so print(HELP)
sys.exit(0)
. So really, you are performing all of this logic here, as the programmer. And then finally, if opt in
"-s"
or "--separator"
—with a "p"
, of course, "--separator"
—then what you actually need to do there is say that the separator
equals the opt_arg
.
03:59
So this is nice, because you’re iterating through the tuple of options, where you have each option and then its corresponding opt_arg
if it has one.
04:08
And then one other thing that would be nice here is to define separator
up top as just a newline, so that that’s the default. Now, I also have these arguments
, which are the operands, and so I can say if not arguments or len(arguments) > 3
,
04:28
then I need to print out—or, I can simply raise SystemExit
with the USAGE
message. Otherwise, though, I can just return—in the correct order based on what main()
has said—I should return separator
, and then these actual arguments.
04:46
So, those will become the operands
that are then passed in to the actual seq()
function. Now, of course, I’ve actually forgotten one thing here.
04:54
What I’ll need to do is I need to actually try to convert all of the arguments to integers, first, just because that’s the format that the seq()
function accepts.
05:05
So I’ll just say arguments = [int(arg) for arg in arguments]
. And then, of course, I’ll except
a ValueError
here, and I will raise again a SystemExit
with USAGE
.
05:24
So now I think that I’m clear and I haven’t forgotten anything. As you can see this parse()
function—it gets these options
and arguments
using getopt
.
05:32
This name getopt
is actually a really apt one because you’re just getting the options and the arguments, and then it’s on you as the programmer to actually enforce this logic here.
05:43
There’s no way in getopt
to quickly and easily define something like a flag, right? Where if the option is present, you just print out the version, right? That’s not something that’s supported by getopt
, but it should work just fine, so let’s see it work.
05:58
Let’s take a look at this as it runs. python seq_getopt.py
and I’ll just use my conventional examples that I’ve done
06:07
for most of this series so far. It seems to be working fine. I’ll do some different intervals there. I’ll even try a start
with a negative interval and then an end
, there, and
06:20
it counts down from 10
to 1
. So, it looks like this works just fine. Let me just try once more. I’ll use the separator flag here…
06:31
and that works pretty darn well, too. So, this is a great option. getopt
really works quite well. The thing to remember is just that when you use getopt
, it’s going to be a little bit more of your logic and your code describing what is done in the command line interface, rather than having something that kind of does it for you. So if you prefer a little bit more manual customization and if you want to really make sure that you’re clear on all of the logic that’s happening in the code, this is a great option, and it’s also quite similar to the C library that does the same thing, so if that’s something that’s attractive to you then definitely go for this. Next up, I’ll cover some external libraries that aren’t included in the Python standard library but are still really useful to work with with command line interfaces.
Become a Member to join the conversation.
khambhayatap on Dec. 29, 2020
sys.stdin
shown in lesson 3.2 onargparse
isn’t working well.I don’t see how will the following code indicate an end to std. input? It’s not working anyway on my Anaconda3.8 and on Windows. I don’t know if it’s the combination that’s creating this issue.
return bytes("".join(sys.stdin), "utf-8")
Post a solution please. I’m also curious how is it working for the author.