user131983
user131983

Reputation: 3937

Error when trying to carry out Exception Handling

I am trying to handle a HTTP IncompleteRead Error, through the code below. However, I find that whenever I call message to see if the Exception Handling works I get the Error 'NoneType' object has no attribute '__getitem__' in the line df = update(currency)[1] despite trying to handle for the case when update returns a NoneType.

import csv
from io import BytesIO
import pandas as pd
import os
from zipfile import ZipFile
from pprint import pprint, pformat
import http.client
import urllib.request
import urllib.parse

def update(ABBRV):
    if ABBRV == 'LAB':
        try:

                my_url = 'http://www.bankofcanada.ca/stats/results/csv'
                data = urllib.parse.urlencode({"lookupPage": "lookup_yield_curve.php",
                                     "startRange": "1986-01-01",
                                     "searchRange": "all"})

                binary_data = data.encode('utf-8')
                req = urllib.request.Request(my_url, binary_data)
                result = urllib.request.urlopen(req)
                zipdata = result.read()

                #In case of http.client.IncompleteRead Error
        except http.client.IncompleteRead as e:
            df = update(ABBRV)[1]
            return df

            zipfile = ZipFile(BytesIO(zipdata))  
            df = pd.read_csv(zipfile.open(zipfile.namelist()[0]))                    
            df = pd.melt(df, id_vars=['Date'])

            def getYear(s):
                x = re.search('(\d+)',s)
                return (float(x.groups()[0]))/100 if x is not None else 'empty string'

            if df is None:
                dict = {}
                symbols = ['Date','Mat', 'VAL', 'ABBRV']
                for l in symbols:
                    dict0[l] = 0
                    df = pd.Series(dict0, name='Data')

            return [df, result]

    if ABBRV != 'LAB':
        raise ValueError

def message(ABBRV):
    df = update(ABBRV)[1]
    if isinstance(df, pd.DataFrame) != 1:
        return 300
    else:
        return 200

Calling the function:

sg = message('LAB')
print sg

Thank You

Edit: Is this portion of code doing nothing to prevent the return of a None type? Also, Edited indentation issues with the code above to reflect Anand S Kumar's suggestions.

if df is None:
    dict = {}
    symbols = ['Date','Mat', 'VAL', 'ABBRV']
    for l in symbols:
        dict0[l] = 0
        df = pd.Series(dict0, name='Data')

Upvotes: 0

Views: 129

Answers (1)

Anand S Kumar
Anand S Kumar

Reputation: 90949

I see few issues in the code -

  1. Inside the try function, if no error occurs you are not returning anything, if you do not return anything from a function, then it would be like the function is returning None , hence assuming there is no error in the url getting side, you will end up returning None and then trying to call [1] for a NoneType , causing the issue in your question.

  2. If an IncompleteRead Exception has occured , you are again calling update(currency) what makes you think if the first time read was unsuccessful , the second time it would be successful? To me it looks like if there is an IncompleteRead Exception , the function would go into infinite recursion and end with the following error after sometime - RuntimeError: maximum recursion depth exceeded .

  3. The condition if ABBRV != 'LAB': raise ValueError is inside the condition - if ABBRV == 'LAB': , the first condition I said (not equals) would never be true, I think you wanted to put that condition outside the if block (would be good to put an else , rather than checking another condition again).

  4. A recommendation is that instead of calling the function as - df = update(ABBRV)[1] maybe you can split them into two lines, get the result of update(ABBRV) first, then check if its None, if it isn't None , then call [1] on it and do the rest of the logic.

Upvotes: 1

Related Questions