News from this site

 Rental advertising space, please contact the webmaster if you need cooperation


+focus
focused

classification  

no classification

tag  

no tag

date  

no datas

Section 24 Abnormal

posted on 2023-05-21 17:05     read(902)     comment(0)     like(21)     collect(2)


10.3 Exceptions

Python uses special objects called exceptions to manage errors that occur during program execution. Whenever an error occurs that overwhelms Python, it creates an exception object. If you write code to handle the exception, the program will continue to run; if the exception is not handled, the program will stop and display a traceback , which contains a report about the exception.

Exceptions are handled using try-except code blocks. The try-except block tells Python what to do when an exception occurs. When using a try-except code block, the program will continue to run even if an exception occurs: displaying a friendly error message you write instead of a traceback that confuses the user.

10.3.1 Handling ZeroDivisionError exceptions

Let's look at a simple error that causes Python to throw an exception. You probably know that you can't divide a number by 0, but let Python do it anyway:

division_calculator.py

print(5/0)

Obviously, Python can't do this, so you'll see a traceback:

  1. Traceback (most recent call last):
  2. File "C:\Users\Administrator\Desktop\1.py", line 1, in <module>
  3. print(5/0)
  4. ZeroDivisionError: division by zero ❶

In the above traceback, the error ZeroDivisionError pointed out at ❶ is an exception object. This is what Python creates when it can't do what you ask it to do. In this case, Python will stop running the program and indicate which exception was thrown, and we can modify the program based on this information. Let's tell Python what to do when this error occurs. That way, we'll be prepared if something like this happens again.

10.3.2 Using try-except code blocks

When you think something might go wrong, write a try-except code block to handle the exception that might be thrown. You tell Python to try to run some code and tell it what to do if that code raises a specified exception.

A try-except code block that handles a ZeroDivisionError exception looks like this:

  1. try:
  2. print(5/0)
  3. except ZeroDivisionError:
  4. print("You can't divide by zero!")

Put the error-causing line print(5/0) in a try block. If the code in the try code block runs without problems, Python will skip the except code block; if the code in the try code block causes an error, Python will find a matching except code block and run the code in it.

In this case, the code in the try block raised a ZeroDivisionError exception, so Python looks for the except block that tells what to do, and runs the code in it. This way, the user sees a friendly error message instead of a traceback:

You can't divide by zero!

If there is other code after the try-except code block, the program will continue to run, because Python has been told how to handle this kind of error. Let's look at an example where the program continues to run after catching an error.

10.3.3 Using exceptions to avoid crashes

When an error occurs, it is especially important to handle the error properly if the program has work to do. This often occurs in programs that require user input; if the program handles invalid input gracefully, it can then prompt the user for valid input without crashing.

Let's create a simple calculator that only performs division:

division_calculator.py

  1. print("Give me two numbers, and I'll divide them.")
  2. print("Enter 'q' to quit.")
  3. while True:
  4. first_number = input("\nFirst number: ")❶
  5. if first_number == 'q':
  6. break
  7. second_number = input("Second number: ")❷
  8. if second_number == 'q':
  9. break
  10. answer = int(first_number) / int(second_number)❸
  11. print(answer)

At ❶, the program prompts the user to enter a number and assigns it to the variable first_number. If the user enters something other than q for exit, the user is prompted to enter a number and assigned to the variable second_number (see ❷). Next, calculate the quotient of these two numbers (see ❸). The program doesn't do anything to handle errors, so when it does a division by 0, it crashes:

  1. Give me two numbers, and I'll divide them.
  2. Enter 'q' to quit.
  3. First number: 5
  4. Second number: 0
  5. Traceback (most recent call last):
  6. File "C:\Users\Administrator\Desktop\1.py", line 10, in <module>
  7. answer = int(first_number) / int(second_number)
  8. ZeroDivisionError: division by zero

It's not good to have a program crash, but it's also not a good idea to let the user see a traceback. Users who do not understand technology will be confused, and malicious users will also learn information that you do not want him to know through traceback. For example, he'll know the names of your program files, and he'll see parts of your code that don't work correctly. Sometimes, a well-trained attacker can use this information to figure out what kind of attack can be launched against your code.

10.3.4 else block

By enclosing code that might cause an error in a try-except code block, you can increase your program's resistance to errors. The error is caused by the line of code that performs the division operation, so it needs to be placed in a try-except code block. This example also includes an else block. Code that depends on the successful execution of the try block should be placed in the else block:

  1. print("Give me two numbers, and I'll divide them.")
  2. print("Enter 'q' to quit.")
  3. while True:
  4. first_number = input("\nFirst number: ")
  5. if first_number == 'q':
  6. break
  7. second_number = input("Second number: ")
  8. if second_number == 'q':
  9. break
  10. try:❶
  11. answer = int(first_number) / int(second_number)
  12. except ZeroDivisionError:❷
  13. print("You can't divide by 0!")
  14. else:❸
  15. print(answer)

Let Python try to perform the division operation in the try code block (see ❶), this code block only contains code that may cause an error. Code that depends on the successful execution of the try block is placed in the else block. In this case, the else block is used to print the result if the division operation was successful (see ❸).

The except block tells Python what to do when a ZeroDivisionError exception occurs (see ❷). If the try block fails with a division by zero error, print a friendly message telling the user how to avoid the error. The program continues to run, and the user doesn't see the traceback at all:

  1. Give me two numbers, and I'll divide them.
  2. Enter 'q' to quit.
  3. First number: 5
  4. Second number: 0
  5. You can't divide by 0!
  6. First number: 5
  7. Second number: 2
  8. 2.5
  9. First number: q

The try-except-else code block works roughly as follows. Python tries to execute the code in the try code block, only the code that may throw an exception needs to be placed in the try statement. Sometimes, there is some code that needs to run only if the try block executes successfully, and this code should be placed in the else block. The except block tells Python what to do if an attempt to run the code in the try block throws the specified exception.

Robust programs can be written by anticipating code where errors may occur. They continue to function even in the face of invalid data or lack of resources, protecting against inadvertent user error and malicious attacks.

10.3.5 Handling FileNotFoundError  exceptions

A common problem when working with files is that the file cannot be found: the file you are looking for may be elsewhere, the file name may be incorrect, or the file may not exist at all. All of these situations can be handled in an intuitive manner using try-except code blocks.

Let's try to read a file that doesn't exist. The following program tries to read the contents of the file alice.txt, but the file is not stored in the same directory as alice.py:

alice.py

  1. filename = 'alice.txt'
  2. with open(filename, encoding='utf-8') as f:
  3. contents = f.read()

Compared with the file opening method earlier in this chapter, there are two differences here. One is to use the variable f to represent the file object, which is a common practice. The second is to specify a value for the parameter encoding, which must be done when the default encoding of the system is inconsistent with the encoding used to read the file.

Python can't read a file that doesn't exist, so it raises an exception:

  1. Traceback (most recent call last):
  2. File "C:\Users\Administrator\Desktop\1.py", line 2, in <module>
  3. with open(filename, encoding='utf-8') as f:
  4. FileNotFoundError: [Errno 2] No such file or directory: 'alice.txt'

The last line of the above traceback reports a FileNotFoundError exception, which is the exception Python creates when it cannot find a file to open. In this case, the error is caused by the function open(). Therefore, to handle this error, a try statement must be placed before the line containing open():

  1. filename = 'alice.txt'
  2. try:
  3. with open(filename, encoding='utf-8') as f:
  4. contents = f.read()
  5. except FileNotFoundError:
  6. print(f"Sorry, the file {filename} does not exist.")

In this example, the try block raises a FileNotFoundError exception, so Python finds an except block that matches that error and runs the code in it. The end result is a friendly error message instead of a traceback:

Sorry, the file alice.txt does not exist.

If the file doesn't exist, the program doesn't do anything, and the error handling code doesn't make much sense. Let's extend this example to see how exception handling can help when you're working with multiple files.

10.3.6 Analyzing text

You can analyze text files containing entire books. Many classic works of literature are simply provided as text files because they are not subject to copyright. The text used in this section comes from Project Gutenberg, a collection of literary works not subject to copyright restrictions. If you're going to use literary texts in your programming projects, this is a great resource.

Let's take the text of the fairy tale "Alice in Wonderland" and try to count how many words it contains. We'll use the method split(), which creates a list of words from a string. Here is the result of calling the method split() on a string containing only the fairy tale name "Alice in Wonderland":

  1. >>> title = "Alice in Wonderland"
  2. >>> title.split()
  3. ['Alice', 'in', 'Wonderland']

The method split() splits the string into multiple parts using spaces as delimiters, and stores these parts in a list. The result is a list containing all the words in the string, although some words may contain punctuation. To figure out how many words Alice's Adventures in Wonderland contains, we'll call split() on the entire novel and count the number of elements in the resulting list to determine the approximate number of words in the fairy tale:

  1. filename = 'alice.txt'
  2. try:
  3. with open(filename, encoding='utf-8') as f:
  4. contents = f.read()
  5. except FileNotFoundError:
  6. print(f"Sorry, the file {filename} does not exist.")
  7. else:
  8. # 计算该文件大致包含多少个单词。
  9. words = contents.split()❶
  10. num_words = len(words)❷
  11. print(f"The file {filename} has about {num_words} words.")❸

We moved the file alice.txt to the correct directory, allowing the try block to execute successfully. At ❶, the method split() is called on the variable contents (which is now a long string containing the entire text of Alice's Adventures in Wonderland) to generate a list containing the all words. When you use len() to determine the length of this list, you can know roughly how many words the original string contains (see ❷). At ❸, print a message stating how many words the file contains. These codes are placed in the else code block because they are only executed if the try code block executes successfully. The output indicates how many words the file alice.txt contains:

The file alice.txt has about 29465 words.

This number is slightly higher because the text file used contains additional information provided by the publisher, but it still manages to estimate the length of the fairy tale Alice's Adventures in Wonderland.

10.3.7 Working with multiple files

Let's analyze a few more books. Before that, let's move most of this program into a function called count_words(). This makes it easier to analyze multiple books:

word_count.py

  1. def count_words(filename):
  2. """计算一个文件大致包含多少个单词。"""
  3. try:
  4. with open(filename, encoding='utf-8') as f:
  5. contents = f.read()
  6. except FileNotFoundError:
  7. print(f"Sorry, the file {filename} does not exist.")
  8. else:
  9. words = contents.split()
  10. num_words = len(words)
  11. print(f"The file {filename} has about {num_words} words.")
  12. filename = 'alice.txt'
  13. count_words(filename)

The code is mostly the same as before, just moved into the function count_words() and increased indentation. It's a good habit to update the comments when you modify the program, so we changed the comments into docstrings and adjusted the wording slightly (see ❶).

You can now write a simple loop that counts how many words are in any text you want to analyze. To do this, store the names of the files to be analyzed in a list, then call count_words() on each file in the list. We'll try to count how many words each of Alice's Adventures in Wonderland, Siddhartha, Moby Dick, and Little Women contain, none of which are subject to copyright limit. I intentionally left siddhartha.txt out of the same directory as word_count.py to show how well the program copes when the file doesn't exist:

  1. def count_words(filename):
  2. """计算一个文件大致包含多少个单词。"""
  3. try:
  4. with open(filename, encoding='utf-8') as f:
  5. contents = f.read()
  6. except FileNotFoundError:
  7. print(f"Sorry, the file {filename} does not exist.")
  8. else:
  9. words = contents.split()
  10. num_words = len(words)
  11. print(f"The file {filename} has about {num_words} words.")
  12. filenames = ['alice.txt', 'siddhartha.txt', 'moby_dick.txt', 'little_women.txt']
  13. for filename in filenames:
  14. count_words(filename)

The file siddhartha.txt does not exist, but this does not in any way prevent the program from processing other files:

  1. The file alice.txt has about 29465 words.
  2. Sorry, the file siddhartha.txt does not exist.
  3. The file moby_dick.txt has about 215830 words.
  4. The file little_women.txt has about 189079 words.

In this case, using a try-except code block provides two important advantages: avoiding the user seeing the traceback, and allowing the program to continue analyzing other files it can find. If you don't catch the FileNotFoundError exception raised because siddhartha.txt cannot be found, the user will see the full traceback and the program will stop after trying to analyze Siddhartha. It doesn't analyze Moby-Dick and Little Women at all.

10.3.8 Silent failure

In the previous example, we told the user that there was a file that could not be found. But it is not necessary to tell the user every time an exception is caught. Sometimes you want the program to remain silent when an exception occurs, and continue to run as if nothing happened. To make the program fail silently, write the try block as usual, but explicitly tell Python to do nothing in the except block. Python has a pass statement that can be used to tell Python to do nothing within a block of code:

  1. def count_words(filename):
  2. """计算一个文件大致包含多少个单词。"""
  3. try:
  4. with open(filename, encoding='utf-8') as f:
  5. contents = f.read()
  6. except FileNotFoundError:
  7. pass
  8. else:
  9. words = contents.split()
  10. num_words = len(words)
  11. print(f"The file {filename} has about {num_words} words.")
  12. filenames = ['alice.txt', 'siddhartha.txt', 'moby_dick.txt', 'little_women.txt']
  13. for filename in filenames:
  14. count_words(filename)

Compared with the previous program, the only difference in this program is the pass statement at ❶. Now, when a FileNotFoundError exception occurs, the code in the except block will be executed, but nothing will happen. When this kind of error occurs, no traceback will appear, and there will be no output. The user will see how many words each file exists, but there is no indication that a file was not found:

  1. The file alice.txt has about 29465 words.
  2. The file moby_dick.txt has about 215830 words.
  3. The file little_women.txt has about 189079 words.

The pass statement also acts as a placeholder, reminding you that you didn't do anything somewhere in the program, and that you might want to do something here later. For example, in this program we might decide to write the names of the files that cannot be found to the file missing_files.txt. Users can't see this file, but we can read it, and then handle any file not found problems.

10.3.9 Deciding which errors to report

Under what circumstances should an error be reported to the user? And under what circumstances should it fail silently? If the user knows which files to analyze, they may want a message to appear when a file is available but not analyzed to explain why. If users just want to see results and don't know which files to analyze, it may not be necessary to tell them that some files don't exist. Displaying information to the user that he does not want to see may reduce the usability of the program. Python's error-handling structure gives you fine-grained control over how much error information you share with your users, and how much information you want to share is up to you.

Well-written and thoroughly tested code is less prone to internal errors, such as syntax or logic errors, but exceptions are possible whenever the program depends on external factors, such as user input, the existence of a specified file, or the presence of a network link. Use experience to determine where in the program to include exception handling blocks and how much information to provide the user when an error occurs.

try it yourself

Exercise 10-6: Addition

A common problem when prompting the user for numeric input is that the user provides text instead of a number. In this case, ValueError will be raised when you try to convert the input to an integer  . Write a program that prompts the user to enter two numbers, adds them, and prints the result. Catch a ValueError exception and print a friendly error message if any value entered by the user is not a number. Test the program you wrote: first enter two numbers, and then enter some text instead of numbers.

  1. try:
  2. first_number = int(input("请输入第一个数字:"))
  3. except ValueError:
  4. print("你输入的不是数字。")
  5. try:
  6. second_number = int(input("请输入第二个数字:"))
  7. except ValueError:
  8. print("你输入的不是数字。")
  9. print(first_number+second_number)

Exercise 10-7: Addition calculator

The code you will write for Exercise 10-6 is placed in a while loop to allow the user to continue entering numbers after making a mistake (entering text instead of numbers).

  1. while True:
  2. try:
  3. first_number = int(input("请输入第一个数字:"))
  4. break
  5. except ValueError:
  6. print("你输入的不是数字。")
  7. continue
  8. while True:
  9. try:
  10. second_number = int(input("请输入第二个数字:"))
  11. break
  12. except ValueError:
  13. print("你输入的不是数字。")
  14. continue
  15. print(first_number+second_number)

Exercises 10-8: Cats and Dogs

Create the files cats.txt and dogs.txt and store at least three cat names in the first file and at least three dog names in the second file. Write a program that attempts to read these files and print their contents to the screen. Put this code in a try-except code block to catch FileNotFound errors and display a friendly message if the file doesn't exist. Move either file to another location and confirm that the code inside the except block will execute correctly.

  1. def ReadFile(filename):
  2. try:
  3. with open(filename,encoding='utf-8') as f:
  4. contents = f.read()
  5. print(contents)
  6. except FileNotFoundError:
  7. print(f"The file {filename} is not exist.")
  8. filename = 'cat.txt'
  9. ReadFile(filename)

Exercises 10-9: Silent cats and dogs

Modify the except block you wrote in Exercise 10-8 so that the program fails silently if any file does not exist.

  1. def ReadFile(filename):
  2. try:
  3. with open(filename,encoding='utf-8') as f:
  4. contents = f.read()
  5. print(contents)
  6. except FileNotFoundError:
  7. pass
  8. filename = 'cat.txt'
  9. ReadFile(filename)
  10. filename = 'cats.txt'
  11. ReadFile(filename)
  12. filename = 'dog.txt'
  13. ReadFile(filename)

Exercise 10-10: Common words

Visit Project Gutenberg and find some books you want to analyze. Download a text file of these works or copy the original text from your browser into a text file.

You can use the method count() to determine how many times a particular word or phrase occurs in a string. For example, the following code counts how many times 'row' occurs in a string:

  1. >>> line = "Row,row,row your boat"
  2. >>> line.count('row')
  3. 2
  4. >>> line.lower().count('row')
  5. 3

Note that converting the string to lowercase using lower() captures all the formatting of the word you're looking for, regardless of its case.

Write a program that reads the files you got at Project Gutenberg and counts how many times the word 'the' occurs in each file. The calculation here is inaccurate because words such as 'then' and 'there' are also counted. Try counting the number of occurrences of 'the ' (with spaces) and see how different the results are.

  1. def ReadFile(filename,word):
  2. try:
  3. with open(filename,encoding='utf-8') as f:
  4. contents = f.read()
  5. except FileNotFoundError:
  6. print(f"The file {filename} is not exist.")
  7. else:
  8. words = contents.split()
  9. times = words.count(word)
  10. print(f"The word {word} appears in the book {times} times.")
  11. filename = 'alice.txt'
  12. word = 'then'
  13. ReadFile(filename,word)



Category of website: technical article > Blog

Author:kimi

link:http://www.pythonblackhole.com/blog/article/25319/262c03d7c482245c7d6f/

source:python black hole net

Please indicate the source for any form of reprinting. If any infringement is discovered, it will be held legally responsible.

21 0
collect article
collected

Comment content: (supports up to 255 characters)