About
Swaroop C H is 29 years of age. He is a coder and startupper. He has previously worked at Yahoo!, Adobe, his own startup and Infibeam.
Views
Support
Personal tools
COLLECTION
Collection
Python el:Εξαιρέσεις
From Notes
Contents |
Εξαιρέσεις
Οι εξαιρέσεις εμφανίζονται όταν ορισμένες εξαιρετικές καταστάσεις συμβαίνουν στο πρόγραμμά σας. Για παράδειγμα, τι συμβαίνει εάν πρόκειται να διαβάσετε ένα αρχείο και το αρχείο δεν υπάρχει; Ή τι συμβαίνει εάν το διαγράψατε κατά λάθος όταν το πρόγραμμα έτρεχε; Τέτοιες καταστάσεις χειρίζονται χρησιμοποιώντας τις εξαιρέσεις.
Παρομοίως, τι συμβαίνει εάν το πρόγραμμά σας είχε μερικές άκυρες εντολές; Αυτό το χειρίζεται η Python η οποία σηκώνει τα χέρια της και σας λέει ότι υπάρχει ένα σφάλμα.
Σφάλματα
Σκεφτείτε μια απλή κλήση της συνάρτησης 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) για αυτό το σφάλμα.
Εξαιρέσεις
Θα δοκιμάσουμε (try) να διαβάσουμε είσοδο από το χρήστη. Πιέστε 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), όταν δεν περιμένει να το δει.
Χειρισμοί εξαιρέσεων
Μπορούμε να χειριστούμε τις εξαιρέσεις χρησιμοποιώντας την εντολή try..except. Βασικά, τοποθετούμε όλες τις συνήθεις εντολές μέσα στην πλοκάδα try και όλους τους χειριστές σφαλμάτων στην πλοκάδα except.
#!/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 και μετά τοποθετούμε τους χειριστές για τα κατάλληλα σφάλματα/εξαιρέσεις στην πρόταση/πλοκάδα except. Η πρόταση except μπορεί να χειριστεί ένα και μόνο καθορισμένο σφάλμα ή εξαίρεση, ή μια λίστα σφαλμάτων/εξαιρέσεων μέσα σε παρένθεση. Εάν δεν παρέχονται καθόλου ονομασίες σφαλμάτων ή εξαιρέσεων, τότε η πρόταση except θα χειριστεί όλες τις εξαιρέσεις και τα σφάλματα.
Σημειώστε ότι πρέπει να υπάρχει τουλάχιστον μια πρόταση except συνδεδεμένη με κάθε πρόταση try. Διαφορετικά για ποιο λόγο να έχετε μια πλοκάδα try;
Εάν οποιοδήποτε σφάλμα ή εξαίρεση δεν χειρίζεται, τότε καλείται ο προκαθορισμένος χειριστής της Python, ο οποίος σταματάει την εκτέλεση του προγράμματος και τυπώνει ένα μήνυμα σφάλματος. Το έχουμε δει ήδη σε ενέργεια παραπάνω.
Μπορείτε επίσης να έχετε μια πρόταση else συνδεδεμένη με μια πλοκάδα try..except. H πρόταση else εκτελείται εάν δεν συμβαίνει καμμία εξαίρεση.
Στο επόμενο παράδειγμα θα δούμε επίσης, πώς να παίρνουμε το αντικείμενο της εξαίρεσης, έτσι ώστε να μπορούμε να ανακτούμε επιπρόσθετες πληροφορίες.
Ανάδειξη των εξαιρέσεων (Raising Exceptions)
Μπορείτε να αναδείξετε εξαιρέσεις χρησιμοποιώντας την εντολή raise, παρέχοντας την ονομασία του σφάλματος/εξαίρεσης και το αντικείμενο της εξαίρεσης είναι πρόκειται να συμβεί.
Το σφάλμα ή η εξαίρεση που μπορείτε να αναδείξετε, πρέπει να είναι κλάση, η οποία άμεσα ή έμμεσα πρέπει να είναι παράγωγη της κλάσης Exception.
#!/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.')
Έξοδος:
$ 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, αναφέρουμε την κλάση του σφάλματος η οποία θα αποθηκεύεται σαν (as) το όνομα μεταβλητής το οποίο συγκρατεί το αντίστοιχο αντικείμενο σφάλματος/εξαίρεσης. Αυτό είναι ανάλογο με τις παραμέτρους και τα ορίσματα σε μια κλήση συνάρτησης. Μέσα σε αυτή την ειδική πρόταση 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)
Πώς δουλεύει:
Κάνουμε το σύνηθες διάβασμα αρχείου, αλλά αυθαίρετα έχουμε εισάγει “ύπνωση” για 2 δευτερόλεπτα αφού τυπωθεί η κάθε γραμμή, χρησιμοποιώντας τη συνάρτηση time.sleep έτσι ώστε το πρόγραμμα να τρέχει αργά (η Python από τη φύση της τρέχει πολύ γρήγορα). Καθώς το πρόγραμμα τρέχει ακόμα, πιέστε ctrl-c για να διακόψετε/ακυρώσετε το πρόγραμμα.
Παρατηρήστε ότι συμβαίνει η εξαίρεση KeyboardInterrupt και το πρόγραμμα εγκαταλείπεται. Πάντως, πριν το πρόγραμμα εγκαταλειφθεί, η πρόταση finally εκτελείται και το αντικείμενο του αρχείου πάντα κλείνεται.
Η εντολή with
Η απόκτηση ενός πόρου στην πλοκάδα 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__. Αυτό είναι που μας βοηθάει να αποφεύγουμε να χρησιμοποιούμε ρητές εντολές try..finally επανειλημμένως.
Περισσότερη συζήτηση για αυτό το θέμα είναι πέρα από το πεδίο αυτού του βιβλίου, έτσι παρακαλώ αναφερθείτε στο PEP343 για πλήρη επεξήγηση.
Σύνοψη
Έχουμε συζητήσει την χρήση των εντολών try..except και try..finally. Έχουμε δει πως να δημιουργούμε τους δικούς μας τύπους εξαιρέσεων και πως να αναδεικνύουμε, επίσης, εξαιρέσεις.
Κατόπιν θα εξερευνήσουμε την πρότυπη βιβλιοθήκη της Python (Python Standard Library).
Please add your comments by clicking on the 'Discussion' link in the left sidebar.