6

I've got a pretty good understanding of python's try-except clause, but I'm encountering problems when trying to put it inside of a function.

>>> def tryAppend(child, parent):
...     try:
...             parent.append(child)
...     except NameError:
...             print "WRONG NAME"
>>> var1 = []
>>> var2 = 'test2'
>>> tryAppend(var2, var1)  #works, no error
>>> tryAppend(foo, var1)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'foo' is not defined

it is almost like python doesn't see the try: statement. Any help is appreciated.

garen
  • 348
  • 2
  • 3
  • 9
  • 1
    var2 is a namespace for the string 'test2'. if you want to enter a string 'foo', then you have to encapsulate it in '' or "", otherwise, if foo is not defined anywhere else in the program as a function or class or whatever, it doesn't work. you're basically trying to use a namespace before declaring it. – momo Nov 10 '10 at 19:19

8 Answers8

11

tryAppend(foo, var1) is evaluated (roughly) in this order:

  1. Fetch the object tryAppend references
  2. Fetch the object foo references
  3. Fetch the object var1 references
  4. Call the first with the second and third as arguments (=do whatever the function tryAppend does, uncluding the try-except)

The error occurs at #2, long before the function and the try block is entered. In fact, the try block cannot to throw a NameError, as the only names used are parent and child, both being arguments and thus always available (if .append does not exist, that's an AttributeError).

In the same way, the following code will not print "caught it" because the exception is raised before the try block is executed:

raise Exception("Catch me if you can")
try:
    pass # do nothing
except:
    print "caught it"
shaneb
  • 1,314
  • 1
  • 13
  • 18
  • 1
    I'm a horrible nitpicky person and I want to say that the try block could raise a name error, say if `parent.append` threw one. But that's silly =). – Katriel Nov 10 '10 at 21:22
5

This has nothing to do with your exception handler. The error you are seeing is because "foo" is not defined anywhere.

cababunga
  • 3,090
  • 15
  • 23
  • 1
    the fact that "foo" is not defined is the point here. Its the lack of definition in this example that causes the error. sometimes you will end up with functions that try to call something that doesn't exist, so the question is: how do we handle these situations? – DanWaters Sep 22 '22 at 21:08
5

The name error is happening before it ever gets into tryAppend. It evaluates the value of foo when trying to pass it to the function. This works:

def tryAppend(child, parent):
    parent.append(child)

var1 = []
try:
    tryAppend(foo, var1)
except NameError:
    print 'WRONG NAME'
Jonathan Sternberg
  • 6,421
  • 7
  • 39
  • 58
  • Thanks Jonathan. I wasn't that that was the process in which variables were evaluated. So that makes it impossible to pass an undefined variable into a function, right? Just trying to make the code as clean as possible.... – garen Nov 10 '10 at 19:09
  • If you want to pass "undefined" variable into a function, you can try to pass in locals() instead. – Jeeyoung Kim Nov 10 '10 at 19:11
  • @garen: Just don't write code that raises NameErrors. Make sure they are always assigned some (sensible!) value in **all** code paths, or die early and barf a meaningful error message when you end up with a state that doesn't allow you to continue (meaningfully). –  Nov 10 '10 at 19:17
2

The NameError is being thrown when the name 'foo' is evaluated, which is before entering the function. Therefore the try/except within the function isn't relevant.

Russell Borogove
  • 18,516
  • 4
  • 43
  • 50
1

For someone who is looking for how to use try except construction inside of the function. I am not sure whether it is a good programming style, but it works.

You can put string arguments to the function. It will be evaluated correctly and then you can use exec inside of the function:

def tryAppend(child, parent):
    try:
        script = parent + '.append(' + child + ')'
        exec script
        return parent
    except NameError:
        print "WRONG NAME"
var1 = []
var2 = 'test2'
tryAppend('var2', 'var1')
tryAppend('foo', 'var1')
Klim
  • 142
  • 2
  • 9
1

foo exception happens even before you enter the function tryAppend() i.e. outside of the function.

Srikar Appalaraju
  • 71,928
  • 54
  • 216
  • 264
1

(Duplicates of this question also here and here)

In Python 3, you can avoid this issue by passing a lambda function into the function containing the try-except. For example, this first block will throw an error:

def trying_fn1(foo):
    try:
        print(foo)
    except ZeroDivisionError:
        print('Cannot divide a number by zero.')

trying_fn1(10/0)

Traceback (most recent call last):
    File "<stdin>", line 1, in <module> trying_fn1(10/0)
ZeroDivisionError: division by zero

But this next function accepts a lambda function which it executes inside the try-except:

def trying_fn2(lambda_foo):
    try:
        print(lambda_foo())
    except ZeroDivisionError:
        print('Cannot divide a number by zero.')
    
lambda_foo = lambda: 10/0
trying_fn2(lambda_foo)
Cannot divide a number by zero.

Hope this helps! If there's a new or better way to do this, happy to take suggestions!

jam7co
  • 43
  • 5
0
def tryAppend(child, parent):
    try:
        global temp_list
        temp_list = [child]
        script = "global " + str(parent) +  '\n' + str(parent) + " = " + str(parent) + " + temp_list" + '\n' + "print('List already exists, only append')"
        return exec(script)
    except NameError:
        print("List does not exist, creating list")
        string_e_1 = "global " + str(parent) +  '\n' + str(parent) + " = temp_list"
        return exec(string_e_1)
  • Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Nov 06 '22 at 00:40