7

Lets say I have the following Python code:

x = some_product()
name        = x.name
first_child = x.child_list[0]
link        = x.link
id          = x.id

A problem might occur in line 3, when x.child_list is None. This obviously gives me a TypeError, saying that:

'NoneType' Object has no attribute '_____getitem_____'

What I want to do is, whenever x.child_list[0] gives a TypeError, simply ignore that line and go to the next line, which is "link = x.link"...

So I'm guessing something like this:

try:
    x = some_product()
    name        = x.name
    first_child = x.child_list[0]
    link        = x.link
    id          = x.id
Except TypeError:
    # Pass, Ignore the statement that gives exception..

What should I put under the Except block? Or is there some other way to do this?

I know I can use If x.child_list is not None: ..., but my actual code is a lot more complicated, and I was wondering if there is a more pythonic way to do this

user2436815
  • 3,455
  • 5
  • 27
  • 40
  • 1
    possible duplicate of [Try/Except in Python: How to properly ignore Exceptions?](http://stackoverflow.com/questions/730764/try-except-in-python-how-to-properly-ignore-exceptions) – towr Mar 29 '14 at 20:26
  • 1
    You can't do it that way, because the rest of the `try` block will be skipped. You would need to put the `except` around just that line where you want to catch the error. Also, what do you want to happen with `first_child` in that case? Do you want it to remain undefined, or do you want it to be set to some value like None? – BrenBarn Mar 29 '14 at 20:26

4 Answers4

11

What you're thinking of is this:

try:
    x = some_product()
    name        = x.name
    first_child = x.child_list[0]
    link        = x.link
    id          = x.id
except TypeError:
    pass

However, really it's best practice to put as little as possible in the try/catch block:

x = some_product()
name = x.name
try:
    first_child = x.child_list[0]
except TypeError:
    pass
link = x.link
id = x.id

However, what you really should do here is avoid try/catch entirely, and do something like this instead:

x = some_product()
name = x.name
first_child = x.child_list[0] if x.child_list else "no child list!"
# Or, something like this:
# first_child = x.child_list[0] if x.child_list else None
link = x.link
id = x.id

Your choice, of course, ultimately depends on your desired behavior--do you want to leave first_child undefined or not, etc.

jdotjdot
  • 16,134
  • 13
  • 66
  • 118
  • 1
    Your second implementation is usually the most pythonic. Ask for forgiveness not for permission! – anthony sottile Mar 29 '14 at 20:30
  • Not sure I completely agree with that. I highly value readability, and the `try/catch` block always hurts readability. I wish it were possible to do it in a single line – jdotjdot Mar 29 '14 at 20:32
  • It depends what you want. The second example leaves `first_child` undefined in the case of an exception, while the third sets it to a placeholder value. They have different behavior, and you have to choose the one you want. – BrenBarn Mar 29 '14 at 20:33
  • Agreed w jdotjdot, it seems to be too much overhead (conceptual and actual) for the situation. Also, you need to specify what exception you are catching (which, in cases with function calls, could cast a net too wide) whereas with the 'if' you are checking a specific condition. – greggo Mar 29 '14 at 20:35
3

Since you only want to handle the exception on that line, only catch it there.

x = some_product()
name        = x.name
try:
  first_child = x.child_list[0]
except TypeError:
  first_child = None
link        = x.link
id          = x.id
Ignacio Vazquez-Abrams
  • 776,304
  • 153
  • 1,341
  • 1,358
2

when you catch an exception you directly move out of the try scope, the better solution is to prevent the exception from occurring by modifying your code in that line to become:

if x.child_list[0] != None:
    first_child = x.child_list[0]

hope this helps.

Edit

as you edited your question and you don't want this solution then the only way is to catch the exception right after that specific line:

try:
    first_child = x.child_list[0]
except TypeError:
    pass
Ammar
  • 1,305
  • 2
  • 11
  • 16
2

A problem might occur in line 3, when x.child_list is None. This obviously gives me a TypeError, saying that:

I think it's bad way to do this with exception. str/unicode, list, tuple types has getitem method or any other custom class may include this method. If you are looking for a solution for working only with tuple/list this code will help you:

x = some_product()
name = x.name
first_child = (lambda x: x[0] if isinstance(x, list) or isinstance(x, tuple) else None)(x.child_list)
link = x.link
id = x.id

And please read PEP8 about formatting python code.

Alexander Gryanko
  • 672
  • 1
  • 10
  • 19