Basic Error Handling
Let’s take a look at some actual Python scripts that make use of
sys.argv, and I’m going to try to point out possible problems that might arise and ways to deal with them—though, of course, I can’t promise that I’ll identify every possible issue you’ll ever run into with
sys.argv. I’m still running into problems when I use it in my own code, and I’ve been working with this for ages.
00:41 And it just prints them back out using this new debugging specifier, which is new in Python 3.8. If you don’t have 3.8, you can just delete this equal sign and it will actually run exactly the same way. It just won’t print out the name of the variable as well as its value.
It’ll just print out the value alone. But all of that is notwithstanding the actual thing that it’s doing here, which is just pointing out that the zeroth index of
sys.argv always contains the filename that’s running, whereas the rest always contains the arguments. So of course, if you run this with no arguments, the rest—the actual args—will just be an empty list.
first index, and then it prints out the reversed version of that argument using Python’s list slicing operator. So I’ll show you how it works. I’ll say
python reverse.py and then I’ll put in my name,
And as you can see, it outputs
And of course, whenever you assume there’s at least one element in a list, that’s a recipe for disaster. So, if I call this with no arguments whatsoever, as you might guess I get an
IndexError: list index out of range because there are zero elements in that list.
And it’s always good practice to write the specific kind of error that you’re excepting, rather than just a more general error. Then, I can print out
1 argument, got 0" and raise
And this will work just fine, on this case. It will at least give your user a little bit more verbose in output so that they can know what’s wrong here. Otherwise, this
IndexError doesn’t say why something went wrong.
So, say I put in
Real Python. All I actually get out is the reverse of
Real, and that’s because these two words are being interpreted as two separate arguments. Now, if that’s the behavior that you want—if you want to only ever reverse the first argument without dealing with any of the others—then this might just be fine.
But you might also want to put in some conditional logic in here to check whether there’s more than one argument and just say, huh, maybe the user thinks that they’re entering, for example, a string, like
"Real Python" in quotes, but in fact, they’re actually entering multiple arguments.
So, that might be something to watch for, and it’s not necessarily an error, but it can be a problem in the logic of your program. Now, one more thing to notice is just that I wrapped in quotes this
"Real Python" in order to reverse the whole thing. I can also wrap in single quotes…
03:59 and I can even not use any quotes at all and I can use the backslash to escape this space character, which means, essentially, don’t treat it as a whitespace character—treat it as just part of this string.
04:12 So, those are the things you can do to make multiple arguments into one, essentially, or into one string argument. Otherwise, any whitespace will delimit a new argument just based on how Bash shells work, and that’s the same in Windows with PowerShell and things like that.
Now, this can be troublesome because when I run this with some arguments—so I can just say
Some Stuff, here—as you’ll notice, before I pop from this list,
sys.argv has one set of contents, and after, it has a different one.
This can definitely be a problem when you have a large codebase and a lot of programmers working on one project, because
sys.argv is always global to your Python invocation. So, if multiple different programmers want to access it, then they might start to run into issues whereby if one programmer modifies it, the next doesn’t actually get the real arguments, but some kind of truncated or modified version of it.
and you could also do the whole, you know, you could just copy
sys.argv if you also needed the filename, but often you really just need the arguments. And then, when you modify things, you should actually just modify the version that you’ve copied over.
So of course, when I run this,
sys.argv always remains constant. This is a very powerful programming practice because it lets anyone anywhere in your code have access to the original system arguments, but you can also just pass around whatever version of this you want to pass around, as long as everyone in your codebase is on the same page.
This is an attempt to mimic the Linux utility
cat in a very basic form. The Linux utility
cat just prints out the contents of some number of files. To demonstrate this, I’ll use some other Linux command line utilities to make a file—so, I’ll say
touch test.txt—and then I’ll use
echo to put some actual text into
As you can see, it does almost the same thing. It adds a newline because that’s how Python’s
print() works, but other than that it’s exactly the same behavior here. Of course,
cat is much more powerful.
It can do any number of files and it can give you some interesting information about them too, but this is just a basic version. But of course, the problem here is that if I run this on some file that doesn’t exist, right—
doesnotexist.txt—then I’ll get a
FileNotFoundError. And again, this is an issue because your user, if they try to use this, will know that there was a problem and they’ll know where it occurred, but they might not know why there was a problem, right?
And now, you can see if I do the same call again, then it tells me a little bit more helpfully,
"The file doesnotexist.txt does not exist, try a different file". Of course, in this case, you should be able to guess from the filename that it doesn’t exist, but in other cases, that won’t be so easy. Now, as an exercise to you, I want you to fix this part of the code, which is the same as what we used in
reverse.py, and so you can use similar strategies to enforce the fact that this takes just one argument at this moment. So, if I call this with no arguments, again, I’ll get an error.
Another interesting thing that you could do would be to try to mimic the behavior of
cat a little bit more closely and print out any number of arguments, or any number of file contents passed in as arguments.
You now know how to handle a lot of the common errors that you might find when you work with
sys.argv in Python. In the next lesson, I’m going to pivot a little bit and show you a little bit more about how Python works as an actual command line interface itself, because there’s a lot more to it than just saying
python and then a Python file.
Become a Member to join the conversation.