# Non-Programmer's Tutorial for Python 3/Dealing with the imperfect

### \...or how to handle errors

### closing files with with

We use the \"with\" statement to open and close files.[^1][^2]

``` python
with open("in_test.txt", "rt") as in_file:
    with open("out_test.txt", "wt") as out_file:
        text = in_file.read()
        data = parse(text)
        results = encode(data)
        out_file.write(results)
    print( "All done." )
```

If some sort of error happens anywhere in this code (one of the files is
inaccessible, the parse() function chokes on corrupt data, etc.) the
\"with\" statements guarantee that all the files will eventually be
properly closed. Closing a file just means that the file is \"cleaned
up\" and \"released\" by our program so that it can be used in another
program.

### catching errors with try

So you now have the perfect program, it runs flawlessly, except for one
detail, it will crash on invalid user input. Have no fear, for Python
has a special control structure for you. It\'s called `try` and it tries
to do something. Here is an example of a program with a problem:

``` python
print("Type Control C or -1 to exit")
number = 1
while number != -1:
   number = int(input("Enter a number: "))
   print("You entered:", number)
```

Notice how when you enter `@#&` it outputs something like:

`Traceback (most recent call last):`\
` File "try_less.py", line 4, in ``<module>`{=html}\
`   number = int(input("Enter a number: "))`\
`ValueError: invalid literal for int() with base 10: '\\@#&'`

As you can see the `int()` function is unhappy with the number `@#&` (as
well it should be). The last line shows what the problem is; Python
found a `ValueError`. How can our program deal with this? What we do is
first: put the place where errors may occur in a `try` block, and
second: tell Python how we want `ValueError`s handled. The following
program does this:

``` python
print("Type Control C or -1 to exit")
number = 1
while number != -1:
    try:
        number = int(input("Enter a number: "))
        print("You entered:", number)
    except ValueError:
        print("That was not a number.")
```

Now when we run the new program and give it `@#&` it tells us \"That was
not a number.\" and continues with what it was doing before.

When your program keeps having some error that you know how to handle,
put code in a `try` block, and put the way to handle the error in the
`except` block.

### Exercises

Update at least the phone numbers program (in section
Dictionaries) so it doesn\'t crash if a
user doesn\'t enter any data at the menu.
`{{Solution|title=Solution|text=
<syntaxhighlight lang="python">
def print_menu():
    print('1. Print Phone Numbers')
    print('2. Add a Phone Number')
    print('3. Remove a Phone Number')
    print('4. Lookup a Phone Number')
    print('5. Quit')
    print()

numbers = {}
menu_choice = 0
print_menu()
while menu_choice != 5:
    try:
        menu_choice = int(input("Type in a number (1-5): "))
        if menu_choice == 1:
            print("Telephone Numbers:")
            for x in numbers.keys():
                print("Name: ", x, "\tNumber:", numbers[x])
            print()
        elif menu_choice == 2:
            print("Add Name and Number")
            name = input("Name: ")
            phone = input("Number: ")
            numbers[name] = phone
        elif menu_choice == 3:
            print("Remove Name and Number")
            name = input("Name: ")
            if name in numbers:
                del numbers[name]
            else:
                print(name, "was not found")
        elif menu_choice == 4:
            print("Lookup Number")
            name = input("Name: ")
            if name in numbers:
                print("The number is", numbers[name])
            else:
                print(name, "was not found")
        elif menu_choice != 5:
            print_menu()
    except ValueError:
        print("That was not a number.")</syntaxhighlight>

}}`{=mediawiki}



[^1]: \"The \'with\'
    statement\"

[^2]: \'The Python \"with\" Statement by
    Example\'
