简体   繁体   中英

Python ValueError Exception not being caught properly

item is a python dictionary

print item.get('body')

gives the following output in some cases:

"1211V1"

however, item.get('body') mostly has a unicode string of the format:

u'{"points_token_id":"327727a0-3909-4132-8fa2-ee45146add1e"}'

I needed to convert the above unicode string to a python dictionary. So I am doing this:

try:
    body_dic = json.loads(item.get('body'))
    body_string = ""

    for body_item in body_dic.keys():
        body_string += body_item + ": {'required': True, 'type': 'resource', 'value': " + str(body_dic.get('body_item')) + "\n\t\t\t\t"

except Exception as e:
    print "futt gayaa"
    print type(e).__name__
    print e.args
    body_string = item.get('body')

and then a bunch of code after this. So in the above the moment item.get('body') comes out to be "1211V1" a ValueError Exception should be raised and the execution flow should get into the except block. Am I right ?

It does not get raised however and the execution flow continues to go onto the next line which is :

for body_item in body_dic.keys():

and then the following exception gets raised:

AttributeError ("'unicode' object has no attribute 'keys'",)

which I get to know if I change the except block in the above to catch a generic exception as :

except Exception as e:
    print "futt gayaa"
    print type(e).__name__
    print e.args
    body_string = item.get('body')

Please help me understand this. In my opinion the moment the first exception gets raised (which in our case should be the ValueError Exception ) the control flow should go into the catch block. Why does it go to the next line of code and then when the Attribute Exception gets raised does it get caught.

Assuming that, as you wrote

print item.get("body")

returns literally

"1211V1"

then the quotation marks are part of the string itself.

So you effectively calling

json.loads('"1211V1"')

where you are loading a JSON string literal--perfectly valid. Then, of course, you get an AttributeError for trying to call .keys() on a unicode object.

If you're using print to debug a problem it might mislead you in this way--you're better off often, if you really want to be sure what the object is that you're having trouble with, writing print(repr(obj)) . In this case that would tell you that item.get("body") is u'"1211V1"' .

So your problem is that you have a sequence of dicts, whose attribute body is a JSON string. It may either be:

"1211V1"

or:

{
    "points_token_id":"327727a0-3909-4132-8fa2-ee45146add1e"
}

This is, a JSON string or a JSON object. By json.loads() ing this string you are always getting a valid Python value, either a Python str or a Python dict , respectively. What you want to do is detect if its one or another:

json_body = json.loads(item['body'])
if type(json_body) is dict:
    for key, value in json_body.items():
        json_body[key] = {'required': True, 'type': 'resource', 'value': value}
    body_string = json.dumps(json_body)
else:
    pass # Handle the "1211V1"

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM