Skip to main content
Engineering LibreTexts

14.5: Raising Exceptions

  • Page ID
    117617
  • \( \newcommand{\vecs}[1]{\overset { \scriptstyle \rightharpoonup} {\mathbf{#1}} } \)

    \( \newcommand{\vecd}[1]{\overset{-\!-\!\rightharpoonup}{\vphantom{a}\smash {#1}}} \)

    \( \newcommand{\dsum}{\displaystyle\sum\limits} \)

    \( \newcommand{\dint}{\displaystyle\int\limits} \)

    \( \newcommand{\dlim}{\displaystyle\lim\limits} \)

    \( \newcommand{\id}{\mathrm{id}}\) \( \newcommand{\Span}{\mathrm{span}}\)

    ( \newcommand{\kernel}{\mathrm{null}\,}\) \( \newcommand{\range}{\mathrm{range}\,}\)

    \( \newcommand{\RealPart}{\mathrm{Re}}\) \( \newcommand{\ImaginaryPart}{\mathrm{Im}}\)

    \( \newcommand{\Argument}{\mathrm{Arg}}\) \( \newcommand{\norm}[1]{\| #1 \|}\)

    \( \newcommand{\inner}[2]{\langle #1, #2 \rangle}\)

    \( \newcommand{\Span}{\mathrm{span}}\)

    \( \newcommand{\id}{\mathrm{id}}\)

    \( \newcommand{\Span}{\mathrm{span}}\)

    \( \newcommand{\kernel}{\mathrm{null}\,}\)

    \( \newcommand{\range}{\mathrm{range}\,}\)

    \( \newcommand{\RealPart}{\mathrm{Re}}\)

    \( \newcommand{\ImaginaryPart}{\mathrm{Im}}\)

    \( \newcommand{\Argument}{\mathrm{Arg}}\)

    \( \newcommand{\norm}[1]{\| #1 \|}\)

    \( \newcommand{\inner}[2]{\langle #1, #2 \rangle}\)

    \( \newcommand{\Span}{\mathrm{span}}\) \( \newcommand{\AA}{\unicode[.8,0]{x212B}}\)

    \( \newcommand{\vectorA}[1]{\vec{#1}}      % arrow\)

    \( \newcommand{\vectorAt}[1]{\vec{\text{#1}}}      % arrow\)

    \( \newcommand{\vectorB}[1]{\overset { \scriptstyle \rightharpoonup} {\mathbf{#1}} } \)

    \( \newcommand{\vectorC}[1]{\textbf{#1}} \)

    \( \newcommand{\vectorD}[1]{\overrightarrow{#1}} \)

    \( \newcommand{\vectorDt}[1]{\overrightarrow{\text{#1}}} \)

    \( \newcommand{\vectE}[1]{\overset{-\!-\!\rightharpoonup}{\vphantom{a}\smash{\mathbf {#1}}}} \)

    \( \newcommand{\vecs}[1]{\overset { \scriptstyle \rightharpoonup} {\mathbf{#1}} } \)

    \(\newcommand{\longvect}{\overrightarrow}\)

    \( \newcommand{\vecd}[1]{\overset{-\!-\!\rightharpoonup}{\vphantom{a}\smash {#1}}} \)

    \(\newcommand{\avec}{\mathbf a}\) \(\newcommand{\bvec}{\mathbf b}\) \(\newcommand{\cvec}{\mathbf c}\) \(\newcommand{\dvec}{\mathbf d}\) \(\newcommand{\dtil}{\widetilde{\mathbf d}}\) \(\newcommand{\evec}{\mathbf e}\) \(\newcommand{\fvec}{\mathbf f}\) \(\newcommand{\nvec}{\mathbf n}\) \(\newcommand{\pvec}{\mathbf p}\) \(\newcommand{\qvec}{\mathbf q}\) \(\newcommand{\svec}{\mathbf s}\) \(\newcommand{\tvec}{\mathbf t}\) \(\newcommand{\uvec}{\mathbf u}\) \(\newcommand{\vvec}{\mathbf v}\) \(\newcommand{\wvec}{\mathbf w}\) \(\newcommand{\xvec}{\mathbf x}\) \(\newcommand{\yvec}{\mathbf y}\) \(\newcommand{\zvec}{\mathbf z}\) \(\newcommand{\rvec}{\mathbf r}\) \(\newcommand{\mvec}{\mathbf m}\) \(\newcommand{\zerovec}{\mathbf 0}\) \(\newcommand{\onevec}{\mathbf 1}\) \(\newcommand{\real}{\mathbb R}\) \(\newcommand{\twovec}[2]{\left[\begin{array}{r}#1 \\ #2 \end{array}\right]}\) \(\newcommand{\ctwovec}[2]{\left[\begin{array}{c}#1 \\ #2 \end{array}\right]}\) \(\newcommand{\threevec}[3]{\left[\begin{array}{r}#1 \\ #2 \\ #3 \end{array}\right]}\) \(\newcommand{\cthreevec}[3]{\left[\begin{array}{c}#1 \\ #2 \\ #3 \end{array}\right]}\) \(\newcommand{\fourvec}[4]{\left[\begin{array}{r}#1 \\ #2 \\ #3 \\ #4 \end{array}\right]}\) \(\newcommand{\cfourvec}[4]{\left[\begin{array}{c}#1 \\ #2 \\ #3 \\ #4 \end{array}\right]}\) \(\newcommand{\fivevec}[5]{\left[\begin{array}{r}#1 \\ #2 \\ #3 \\ #4 \\ #5 \\ \end{array}\right]}\) \(\newcommand{\cfivevec}[5]{\left[\begin{array}{c}#1 \\ #2 \\ #3 \\ #4 \\ #5 \\ \end{array}\right]}\) \(\newcommand{\mattwo}[4]{\left[\begin{array}{rr}#1 \amp #2 \\ #3 \amp #4 \\ \end{array}\right]}\) \(\newcommand{\laspan}[1]{\text{Span}\{#1\}}\) \(\newcommand{\bcal}{\cal B}\) \(\newcommand{\ccal}{\cal C}\) \(\newcommand{\scal}{\cal S}\) \(\newcommand{\wcal}{\cal W}\) \(\newcommand{\ecal}{\cal E}\) \(\newcommand{\coords}[2]{\left\{#1\right\}_{#2}}\) \(\newcommand{\gray}[1]{\color{gray}{#1}}\) \(\newcommand{\lgray}[1]{\color{lightgray}{#1}}\) \(\newcommand{\rank}{\operatorname{rank}}\) \(\newcommand{\row}{\text{Row}}\) \(\newcommand{\col}{\text{Col}}\) \(\renewcommand{\row}{\text{Row}}\) \(\newcommand{\nul}{\text{Nul}}\) \(\newcommand{\var}{\text{Var}}\) \(\newcommand{\corr}{\text{corr}}\) \(\newcommand{\len}[1]{\left|#1\right|}\) \(\newcommand{\bbar}{\overline{\bvec}}\) \(\newcommand{\bhat}{\widehat{\bvec}}\) \(\newcommand{\bperp}{\bvec^\perp}\) \(\newcommand{\xhat}{\widehat{\xvec}}\) \(\newcommand{\vhat}{\widehat{\vvec}}\) \(\newcommand{\uhat}{\widehat{\uvec}}\) \(\newcommand{\what}{\widehat{\wvec}}\) \(\newcommand{\Sighat}{\widehat{\Sigma}}\) \(\newcommand{\lt}{<}\) \(\newcommand{\gt}{>}\) \(\newcommand{\amp}{&}\) \(\definecolor{fillinmathshade}{gray}{0.9}\)
    Learning Objectives

    By the end of this section you should be able to

    • Use a raise statement to indicate that user input is invalid.
    • Explain the flow of execution when an exception is raised.

    The raise statement

    A program can raise an exception when an error is detected. Raising an exception forces a program to deal with the error. If the exception is not handled using try and except, the program displays an error message and terminates.

    Example 14.6: Invalid pizza size

    The following class represents a pizza for sale. The SIZES dictionary maps an abbreviation to a size's name and price. Line 11 checks if the size received by the constructor is in the dictionary. Line 12 raises a ValueError with specific error message.

        Large pizza for $9.99
        Traceback (most recent call last):
          File "pizza.py", line 23, in <module>
            p2 = Pizza("Z")
          File "pizza.py", line 12, in __init__
            raise ValueError(f"Unknown size '{size}'")
        ValueError: Unknown size 'Z'
    

    Raising an exception in a constructor prevents an invalid object from being constructed. In the example, p1 is constructed but p2 is not constructed.

    Concepts in Practice: Predicting output with raise

    For each code snippet, what is the output?

    Concepts in Practice \(\PageIndex{1}\): Predicting output with raise

    1

    class Pizza:

    2

     

    3

    SIZES = {

    4

    "S": ("Small", 5.99),

    5

    "M": ("Medium", 7.99),

    6

    "L": ("Large", 9.99),

    7

    "XL": ("X-Large", 11.99),

    8

    }

    9

     

    10

    def __init__(self, size):

    11

    if size not in Pizza.SIZES:

    12

    raise ValueError(f"Unknown size '{size}'")

    13

    self.size = size

    14

     

    15

    def __str__(self):

    16

    name, price = Pizza.SIZES[self.size]

    17

    return f"{name} pizza for ${price}"

    18

     

    19

    if __name__ == "__main__":

    20

    p1 = Pizza("L")

    21

    print(p1)

    22

    p2 = Pizza("Z")

    23

    print(p2)
    1. Medium pizza for $7.99
    2. ValueError: Unknown size 'M'
    3. TypeError: missing argument
    Answer

    a. "M" is a valid size, so the Pizza object is constructed.

    Concepts in Practice \(\PageIndex{2}\): Predicting output with raise

    raise PizzaError("Invalid size")

    1. Invalid size
    2. PizzaError: Invalid size
    3. NameError: name 'PizzaError' is not defined
    Answer

    c. PizzaError is not a built-in exception type.

    Concepts in Practice \(\PageIndex{3}\): Predicting output with raise

    raise ValueError

    1. ValueError
    2. NameError: name 'ValueError' is not defined
    3. SyntaxError: Missing parenthesis in call to 'ValueError'
    Answer

    a. An exception can be raised without providing an error message. In this case, the error message is empty, but the exception name is still printed.

    Try It: Language objects

    The file top27.csv is based on Wikipedia's list of languages by number of native speakers. A linguist would like to work with this data in an object-oriented way and has already defined a Language class. However, the code is not working correctly because of errors in the CSV file. (The CSV program cannot be changed because the program's purpose is to detect these kinds of errors.)

    Your task is to modify the constructor to raise a ValueError in the following situations:

    • If the line does not have exactly four values (separated by commas).
    • If the number of speakers is not a positive floating point number.

    Note: The provided top27.csv includes mistakes for English, Korean, and French. Your program should raise a ValueError only for these languages. No other errors (including IndexError) should be raised.

    Interactive Code
    class Language:
        
        def __init__(self, line):
            data = line.split(',')
            self.name = data[0]
            self.speakers = float(data[1])
            self.family = data[2]
            self.branch = data[3]
    
        def __str__(self):
            return f"{self.name} ({self.speakers} million)"
    
    
    if __name__ == "__main__":
        valid = []
        data = open("top27.csv")
        data.readline()  # Skip first line
        for line in data:
            try:
                lang = Language(line)
                valid.append(lang)
            except ValueError as err:
                print(err)
                print(line)
        for lang in valid:
            print(lang)
    
     
    top27.csv

    Language,Native speakers (millions),Language family,Branch
    Mandarin Chinese (incl. Standard Chinese but excl. other varieties),939,Sino-Tibetan,Sinitic
    Spanish,485,Indo-European,Romance
    English,380+,Indo-European,Germanic
    Hindi (excl. Urdu and other languages),345,Indo-European,Indo-Aryan
    Portuguese,236,Indo-European,Romance
    Bengali,234,Indo-European,Indo-Aryan
    Russian,147,Indo-European,Balto-Slavic
    Japanese,123,Japonic,Japanese
    Yue Chinese (incl. Cantonese),86.1,Sino-Tibetan,Sinitic
    Vietnamese,85,Austroasiatic,Vietic
    Turkish,84,Turkic,Oghuz
    Wu Chinese (incl. Shanghainese),83.4,Sino-Tibetan,Sinitic
    Marathi,83.2,Indo-European,Indo-Aryan
    Telugu,83,Dravidian,South-Central
    Korean,81.7,Koreanic
    French,-80.8,Indo-European,Romance
    Tamil,78.6,Dravidian,South
    Egyptian Spoken Arabic (excl. Saidi Arabic),77.4,Afroasiatic,Semitic
    Standard German,75.3,Indo-European,Germanic
    Urdu (excl. Hindi),70.6,Indo-European,Indo-Aryan
    Javanese,68.3,Austronesian,Malayo-Polynesian
    Western Punjabi (excl. Eastern Punjabi),66.7,Indo-European,Indo-Aryan
    Italian,64.6,Indo-European,Romance
    Gujarati,57.1,Indo-European,Indo-Aryan
    Iranian Persian (excl. Dari and Tajik),57.2,Indo-European,Iranian
    Bhojpuri,52.3,Indo-European,Indo-Aryan
    Hausa,51.7,Afroasiatic,Chadic

    Answer

    class Language:

    def __init__(self, line):
    data = line.split(',')
    if len(data) != 4:
    raise ValueError("incorrect number of values")
    self.name = data[0]
    self.speakers = float(data[1])
    if self.speakers < 0:
    raise ValueError("speakers cannot be negative")
    self.family = data[2]
    self.branch = data[3]

    def __str__(self):
    return f"{self.name} ({self.speakers} million)"

    if __name__ == "__main__":
    valid = []
    data = open("top27.csv")
    data.readline() # Skip first line
    for line in data:
    try:
    lang = Language(line)
    valid.append(lang)
    except ValueError as err:
    print(err)
    print(line)
    for lang in valid:
    print(lang)

    Try It: Looking up keys

    When looking up a value in a dictionary, a key has to match exactly. Ex: Given fruit = {"apple": 1, "banana": 2}, the expression fruit["Apple"] raises a KeyError because "Apple" is not the same as "apple". Likewise, fruit["NANA"] raises a KeyError because "nana" does not exactly match "banana".

    Implement the lookup() function. This function tries to find a key in the dictionary that matches the search term. A key matches if the search term is a substring of the key, ignoring case. Ex: The key "banana" matches the search term "NANA".

    If no matching keys are found, lookup() should raise a KeyError with the message "search term not found". If multiple matches are found, lookup() should raise a KeyError with the message "multiple keys found". Otherwise, lookup() should return both the key and the value for the matching item in the dictionary.

    Given the books.csv file, the output should be:

        Found: ('Pride and Prejudice', 9780141439518)
        Found: ('The Hobbit', 9780547928227)
        Error: search term not found
        Error: multiple keys found
    Interactive Code
    def lookup(dictionary, search_term):
        # TODO find the matching key
        return key, dictionary[key]
    
    
    if __name__ == "__main__":
    
        # Read books from the file
        books = {}
        for line in open("books.csv"):
            title, isbn = line.split(",")
            books[title] = int(isbn)
    
        # Try looking up some books    
        for term in ["PREJ", "hob", "1984", "The"]:
            try:
                result = lookup(books, term)
                print("Found:", result)
            except KeyError as err:
                print("Error:", err)
    
     
    books.csv

    The Fault in Our Stars,9780142424179
    To Kill a Mockingbird,9780061120084
    Harry Potter and the Sorcerer's Stone,9780545010221
    The Catcher in the Rye,9780316769488
    The Alchemist,9780062315007
    Pride and Prejudice,9780141439518
    The DaVinci Code,9781400079179
    Fahrenheit 451,9781451673319
    Where the Sidewalk Ends,9780060256678
    The Hobbit,9780547928227

    Answer

    def lookup(dictionary, search_term):
    search_term = search_term.lower()
    hits = []
    for key in dictionary:
    if search_term in key.lower():
    hits.append(key)
    if len(hits) == 0:
    raise KeyError("search term not found")
    if len(hits) > 1:
    raise KeyError("multiple keys found")
    key = hits[0]
    return key, dictionary[key]

    if __name__ == "__main__":

    # Read books from the file
    books = {}
    for line in open("books.csv"):
    title, isbn = line.split(",")
    books[title] = int(isbn)

    # Try looking up some books
    for term in ["PREJ", "hob", "1984", "The"]:
    try:
    result = lookup(books, term)
    print("Found:", result)
    except KeyError as err:
    print("Error:", err)


    This page titled 14.5: Raising Exceptions is shared under a CC BY 4.0 license and was authored, remixed, and/or curated by OpenStax via source content that was edited to the style and standards of the LibreTexts platform.