Δημοσιεύτηκε: 04 Ιουν 2009, 17:46
Καλησπέρα παιδιά, υποβάλω το κεφάλαιο 15 για έλεγχο:
και η μετάφρασή του:
- Κώδικας: Επιλογή όλων
Introduction
Exceptions occur when certain exceptional situations occur in your program. For example, what if you are going to read a file and the file does not exist? Or what if you accidentally deleted it when the program was running? Such situations are handled using exceptions.
Similarly, what if your program had some invalid statements? This is handled by Python which raises its hands and tells you there is an error.
Errors
Consider a simple print function call. What if we misspelt print as Print? Note the capitalization. In this case, Python raises a syntax error.
>>> Print('Hello World')
Traceback (most recent call last):
File "<pyshell#0>", line 1, in <module>
Print('Hello World')
NameError: name 'Print' is not defined
>>> print('Hello World')
Hello World
Observe that a NameError is raised and also the location where the error was detected is printed. This is what an error handler for this error does.
Exceptions
We will try to read input from the user. Press ctrl-d and see what happens.
>>> s = input('Enter something --> ')
Enter something -->
Traceback (most recent call last):
File "<pyshell#2>", line 1, in <module>
s = input('Enter something --> ')
EOFError: EOF when reading a line
Python raises an error called EOFError which basically means it found an end of file symbol (which is represented by ctrl-d) when it did not expect to see it.
Handling Exceptions
We can handle exceptions using the try..except statement. We basically put our usual statements within the try-block and put all our error handlers in the except-block.
#!/usr/bin/python
# Filename: try_except.py
try:
text = input('Enter something --> ')
except EOFError:
print('Why did you do an EOF on me?')
except KeyboardInterrupt:
print('You cancelled the operation.')
else:
print('You entered {0}'.format(text))
Output:
$ python try_except.py
Enter something --> # Press ctrl-d
Why did you do an EOF on me?
$ python try_except.py
Enter something --> # Press ctrl-c
You cancelled the operation.
$ python try_except.py
Enter something --> no exceptions
You entered no exceptions
How It Works:
We put all the statements that might raise exceptions/errors inside the try block and then put handlers for the appropriate errors/exceptions in the except clause/block. The except clause can handle a single specified error or exception, or a parenthesized list of errors/exceptions. If no names of errors or exceptions are supplied, it will handle all errors and exceptions.
Note that there has to be at least one except clause associated with every try clause. Otherwise, what's the point of having a try block?
If any error or exception is not handled, then the default Python handler is called which just stops the execution of the program and prints an error message. We have already seen this in action above.
You can also have an else clause associated with a try..except block. The else clause is executed if no exception occurs.
In the next example, we will also see how to get the exception object so that we can retrieve additional information.
Raising Exceptions
You can raise exceptions using the raise statement by providing the name of the error/exception and the exception object that is to be thrown.
The error or exception that you can arise should be class which directly or indirectly must be a derived class of the Exception class.
#!/usr/bin/python
# Filename: raising.py
class ShortInputException(Exception):
'''A user-defined exception class.'''
def __init__(self, length, atleast):
Exception.__init__(self)
self.length = length
self.atleast = atleast
try:
text = input('Enter something --> ')
if len(text) < 3:
raise ShortInputException(len(text), 3)
# Other work can continue as usual here
except EOFError:
print('Why did you do an EOF on me?')
except ShortInputException as ex:
print('ShortInputException: The input was {0} long, expected at least {1}'\
.format(ex.length, ex.atleast))
else:
print('No exception was raised.')
Output:
$ python raising.py
Enter something --> a
ShortInputException: The input was 1 long, expected at least 3
$ python raising.py
Enter something --> abc
No exception was raised.
How It Works:
Here, we are creating our own exception type. This new exception type is called ShortInputException. It has two fields - length which is the length of the given input, and atleast which is the minimum length that the program was expecting.
In the except clause, we mention the class of error which will be stored as the variable name to hold the corresponding error/exception object. This is analogous to parameters and arguments in a function call. Within this particular except clause, we use the length and atleast fields of the exception object to print an appropriate message to the user.
Try .. Finally
Suppose you are reading a file in your program. How do you ensure that the file object is closed properly whether or not an exception was raised? This can be done using the finally block. Note that you can use an except clause along with a finally block for the same corresponding try block. You will have to embed one within another if you want to use both.
#!/usr/bin/python
# Filename: finally.py
import time
try:
f = open('poem.txt')
while True: # our usual file-reading idiom
line = f.readline()
if len(line) == 0:
break
print(line, end='')
time.sleep(2) # To make sure it runs for a while
except KeyboardInterrupt:
print('!! You cancelled the reading from the file.')
finally:
f.close()
print('(Cleaning up: Closed the file)')
Output:
$ python finally.py
Programming is fun
When the work is done
if you wanna make your work also fun:
!! You cancelled the reading from the file.
(Cleaning up: Closed the file)
How It Works:
We do the usual file-reading stuff, but we have arbitrarily introduced sleeping for 2 seconds after printing each line using the time.sleep function so that the program runs slowly (Python is very fast by nature). When the program is still running, press ctrl-c to interrupt/cancel the program.
Observe that the KeyboardInterrupt exception is thrown and the program quits. However, before the program exits, the finally clause is executed and the file object is always closed.
The with statement
Acquiring a resource in the try block and subsequently releasing the resource in the finally block is a common pattern. Hence, there is also a with statement that enables this to be done in a clean manner:
#!/usr/bin/python
# Filename: using_with.py
with open("poem.txt") as f:
for line in f:
print(line, end='')
How It Works:
The output should be same as the previous example. The difference here is that we are using the open function with the with statement - we leave the closing of the file to be done automatically by with open.
What happens behind the scenes is that there is a protocol used by the with statement. It fetches the object returned by the open statement, let's call it "thefile" in this case.
It always calls the thefile.__enter__ function before starting the block of code under it and always calls thefile.__exit__ after finishing the block of code.
So the code that we would have written in a finally block is should be taken care of automatically by the __exit__ method. This is what helps us to avoid having to use explicit try..finally statements repeatedly.
More discussion on this topic is beyond scope of this book, so please refer PEP 343 for comprehensive explanation.
Summary
We have discussed the usage of the try..except and try..finally statements. We have seen how to create our own exception types and how to raise exceptions as well.
Next, we will explore the Python Standard Library.
και η μετάφρασή του:
- Κώδικας: Επιλογή όλων
Εξαιρέσεις (Exceptions)
Εισαγωγή
Οι εξαιρέσεις εμφανίζονται όταν ορισμένες εξαιρετικές καταστάσεις συμβαίνουν στο πρόγραμμά σας. Για παράδειγμα, τι συμβαίνει εάν πρόκειται να διαβάσετε ένα αρχείο και το αρχείο δεν υπάρχει; Ή τι συμβαίνει εάν ατυχώς το διαγράψατε όταν το πρόγραμμα έτρεχε; Τέτοιες καταστάσεις χειρίζονται χρησιμοποιώντας τις εξαιρέσεις. Παρομοίως, τι συμβαίνει εάν το πρόγραμμά σας είχε μερικές άκυρες εντολές; Αυτό το χειρίζεται η Python η οποία σηκώνει τα χέρια της και σας λέει ότι υπάρχει ένα σφάλμα.
Σφάλματα (Errors)
Σκεφτείτε μια απλή print κλήση συνάρτησης. Τι συμβαίνει αν γράψαμε ανορθόγραφα Print αντί για το σωστό print; Παρατηρήστε το κεφαλαίο P αντί για p. Σε αυτή την περίπτωση η Python αναδεικνύει (raises) ένα συντακτικό σφάλμα (syntax error).
>>> Print('Hello World')
Traceback (most recent call last):
File "<pyshell#0>", line 1, in <module>
Print('Hello World')
NameError: name 'Print' is not defined
>>> print('Hello World')
Hello World
Παρατηρήστε ότι το NameError αναδυκνείεται καθώς επίσης τυπώνεται και η θέση που ανιχνεύεται το σφάλμα. Αυτό είναι που κάνει ο χειριστής σφάλματος (error handler) για αυτό το σφάλμα.
Εξαιρέσεις
Θα δοκιμάσουμε να διαβάσουμε είσοδο από το χρήστη. Πιέστε ctrl-d και κοιτάξτε τι συμβαίνει.
>>> s = input('Enter something --> ')
Enter something -->
Traceback (most recent call last):
File "<pyshell#2>", line 1, in <module>
s = input('Enter something --> ')
EOFError: EOF when reading a line
Η Python αναδυκνύει ένα σφάλμα, που ονομάζεται EOFError, που βασικά σημαίνει ότι βρήκε ένα σύμβολο end of file (που αντιπροσωπεύεται από το ctrl-d), όταν δεν περιμένει να το δει.
Χειρισμοί με τις εξαιρέσεις (Handling Exceptions)
Μπορούμε να χειριστούμε τις εξαιρέσεις χρησιμοποιώντας την εντολή try...except. Βασικά, τοποθετούμε όλες τις συνήθεις εντολές μέσα στην πλοκάδα try (try-block) και όλους τους χειριστές σφαλμάτων στην πλοκάδα except (except-block).
#!/usr/bin/python
# Filename: try_except.py
try:
text = input('Enter something --> ')
except EOFError:
print('Why did you do an EOF on me?')
except KeyboardInterrupt:
print('You cancelled the operation.')
else:
print('You entered {0}'.format(text))
Έξοδος:
$ python try_except.py
Enter something --> # Press ctrl-d
Why did you do an EOF on me?
$ python try_except.py
Enter something --> # Press ctrl-c
You cancelled the operation.
$ python try_except.py
Enter something --> no exceptions
You entered no exceptions
Πως δουλεύει:
Τοποθετούμε όλες τις εντολές, που ίσως αναδεικνύουν εξαιρέσεις/σφάλματα μέσα στην πλοκάδα try και μετά τοποθετούμε τους χειριστές για τα κατάλληλα σφάλματα/εξαιρέσεις στην πρόταση (clause)/πλοκάδα. Η πρόταση except μπορεί να χειριστεί ένα και μόνο καθορισμένο σφάλμα ή εξαίρεση, ή μια λίστα σφαλμάτων/εξαιρέσεων μέσα σε παρένθεση. Εάν δεν παρέχονται καθόλου ονομασίες σφαλμάτων ή εξαιρέσεων, τότε η πρόταση except θα χειριστεί όλες (all) τις εξαιρέσεις και τα σφάλματα.
Σημειώστε ότι πρέπει να υπάρχει τουλάχιστον μια πρόταση except συνδεδεμένη με κάθε πρόταση try. Διαφορετικά για ποιο λόγο να έχετε μια πλοκάδα try;
Εάν οποιοδήποτε σφάλμα ή εξαίρεση δεν χειρίζεται, τότε καλείται ο προκαθορισμένος χειριστής της Python, ο οποίος σταματάει την εκτέλεση του προγράμματος και τυπώνει ένα μήνυμα σφάλματος. Το έχουμε δει ήδη σε ενέργεια παραπάνω.
Μπορείτε επίσης να έχετε μια πρόταση else συνδεδεμένη με μια πλοκάδα try...except. H πρόταση else εκτελείται εάν δεν συμβαίνει καμμία εξαίρεση. Στο επόμενο παράδειγμα θα δούμε επίσης, πως να παίρνουμε το αντικείμενο της εξαίρεσης, έτσι ώστε να μπορούμε να ανακτούμε επιπρόσθετες πληροφορίες.
Ανάδειξη των εξαιρέσεων (Raising Exceptions)
Μπορείτε να αναδείξετε εξαιρέσεις χρησιμοποιώντας την εντολή raise, παρέχοντας την ονομασία του σφάλματος/εξαίρεσης και το αντικείμενο της εξαίρεσης είναι για να ρίχνεται (thrown). Το σφάλμα ή η εξαίρεση που μπορείτε να αναδείξετε, πρέπει να είναι τάξη, η οποία απευθείας ή έμμεσα πρέπει να είναι παράγωγη, της τάξης Exception.
class ShortInputException(Exception):
'''A user-defined exception class.'''
def __init__(self, length, atleast):
Exception.__init__(self)
self.length = length
self.atleast = atleast
try:
text = input('Enter something --> ')
if len(text) < 3:
raise ShortInputException(len(text), 3)
# Other work can continue as usual here
except EOFError:
print('Why did you do an EOF on me?')
except ShortInputException as ex:
print('ShortInputException: The input was {0} long, expected at least {1}'\
.format(ex.length, ex.atleast))
else:
print('No exception was raised.')
Έξοδος:
$ python raising.py
Enter something --> a
ShortInputException: The input was 1 long, expected at least 3
$ python raising.py
Enter something --> abc
No exception was raised.
Πως δουλεύει:
Εδώ δημιουργούμε το δικό μας τύπο εξαίρεσης. Αυτός ο νέος τύπος εξαίρεσης ονομάζεται ShortInputException. Έχει δύο πεδία το length, το οποίο είναι το μήκος της δοθείσας εισόδου και το atleast που είναι το ελάχιστο μήκος που το πρόγραμμα περίμενε. Στην πρόταση except, αναφέρουμε την τάξη του σφάλματος η οποία θα αποθηκεύεται σαν το όνομα μεταβλητής, για να συγκρατεί το αντίστοιχο αντικείμενο σφάλματος/εξαίρεσης. Αυτό είναι ανάλογο με τους παραμέτρους και τα ορίσματα σε μια κλήση συνάρτησης. Μέσα σε αυτή την ειδική πρόταση except, χρησιμοποιούμε τα πεδία length και atleast του αντικειμένου της εξαίρεσης, για να τυπώσουμε ένα κανονικό μήνυμα στο χρήστη.
Η εντολή try...finally
Υποθέστε ότι διαβάζετε ένα αρχείο στο πρόγραμμά σας. Πως επιβεβαιώνετε ότι το αντικείμενο του αρχείου έχει κλειστεί κανονικά,είτε η εξαίρεση αναδείχθηκε είτε όχι; Αυτό μπορεί να γίνει χρησιμοποιώντας την πλοκάδα finally. Σημειώστε ότι μπορείτε να χρησιμοποιήσετε μια πρόταση except μαζί με την πλοκάδα finally για την ίδια αντιστοιχούσα πλοκάδα try. Πρέπει να ενσωματώσετε τη μια μέσα στην άλλη, εάν θέλετε να χρησιμοποιήσετε και τις δύο.
#!/usr/bin/python
# Filename: finally.py
import time
try:
f = open('poem.txt')
while True: # our usual file-reading idiom
line = f.readline()
if len(line) == 0:
break
print(line, end='')
time.sleep(2) # To make sure it runs for a while
except KeyboardInterrupt:
print('!! You cancelled the reading from the file.')
finally:
f.close()
print('(Cleaning up: Closed the file)')
Έξοδος:
$ python finally.py
Programming is fun
When the work is done
if you wanna make your work also fun:
!! You cancelled the reading from the file.
(Cleaning up: Closed the file)
Πως δουλεύει:
Κάνουμε το σύνηθες διάβασμα αρχείου (file-reading), αλλά αυθαίρετα έχουμε εισάγει “ύπνωση” για 2 δευτερόλεπτα, αφού τυπωθεί η κάθε γραμμή, χρησιμοποιώντας τη συνάρτηση time.sleep έτσι ώστε το πρόγραμμα να τρέχει αργά (η Python από τη φύση της τρέχει πολύ γρήγορα). Όταν το πρόγραμμα τρέχει ακόμα, πιέστε ctrl-c για να διακόψετε/ακυρώσετε το πρόγραμμα.
Παρατηρήστε ότι η εξαίρεση KeyboardInterrupt ρίχνεται και το πρόγραμμα εγκαταλείπεται. Πάντως, πριν το πρόγραμμα εγκαταλειφθεί, η πρόταση finally εκτελείται και το αντικείμενο του αρχείου πάντα κλείνεται.
Η εντολή with (The with statement)
Η απόκτηση ενός πόρου στην πλοκάδα try και ακολούθως η απελευθέρωση του πόρου στην πλοκάδα finally είναι μια συνηθισμένη σχηματομορφή. Γι αυτό το λόγο υπάρχει και η εντολή with, η οποία το κάνει ικανό να γίνει με καθαρό τρόπο:
#!/usr/bin/python
# Filename: using_with.py
with open("poem.txt") as f:
for line in f:
print(line, end='')
Πως δουλεύει:
Η έξοδος θα έπρεπε να είναι ίδια με το προηγούμενο παράδειγμα. Η διαφορά εδώ είναι ότι χρησιμοποιούμε τη συνάρτηση open με την εντολή with. Aφήνουμε το κλείσιμο του αρχείου να γίνει αυτόματα με το with open. Αυτό που συμβαίνει πίσω από τη σκηνή είναι ότι υπάρχει ένα πρωτόκολλο που χρησιμοποιείται με την εντολή with. Πιάνει το αντικείμενο που επέστρεψε με την εντολή open και ας το ονομάσουμε “ thefile” σε αυτή την περίπτωση. Πάντα καλεί τη συνάρτηση thefile.__enter__ πριν αρχίσει η πλοκάδα του κώδικα κάτω από αυτό, και πάντα καλεί το thefile.__exit__ , αφού τελειώσει η πλοκάδα του κώδικα. Έτσι ο κώδικας που θα είχαμε γράψει σε μια πλοκάδα finally θα έπρεπε να φροντίζεται αυτόματα από τη μέθοδο __exit__. Αυτό είναι που μας βοηθάει να αποφεύγουμε να χρησιμοποιούμε ρητές εντολές επανειλημμένως.
Περισσότερη συζήτηση για αυτό το θέμα είναι πέρα από το πεδίο αυτού του βιβλίου, έτσι παρακαλώ αναφερθείτε στο PEP343 για πλήρη επεξήγηση.
Σύνοψη
Έχουμε συζητήσει την χρήση των εντολών try...except και try...finally. Έχουμε δει πως να δημιουργούμε τους δικούς μας τύπους εξαιρέσεων και πως να αναδεικνύουμε, επίσης, εξαιρέσεις.
Κατόπιν θα εξερευνήσουμε την πρότυπη βιβλιοθήκη της Python (Python Standard Library).