Join us and get access to thousands of tutorials and a community of expert Pythonistas.

Unlock This Lesson

This lesson is for members only. Join us and get access to thousands of tutorials and a community of expert Pythonistas.

Unlock This Lesson

Hint: You can adjust the default video playback speed in your account settings.
Hint: You can set your subtitle preferences in your account settings.
Sorry! Looks like there’s an issue with video playback 🙁 This might be due to a temporary outage or because of a configuration issue with your browser. Please refer to our video player troubleshooting guide for assistance.

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.

khambhayatap on Dec. 29, 2020

sys.stdin shown in lesson 3.2 on argparse 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.

Become a Member to join the conversation.