[SOLVED] Is it possible to define function that allows invalid input in Python

Issue

I have defined a function that checks if my statement is valid and assigns it to a variable which is being fed as a string, because before assignment this variable does not exist yet. The function is as follows:

#Check if item is in HTML otherwise appoint NOT FOUND
def try_except(try_statement, variable):
    try:
        locals()[variable]=try_statement
    except:
        locals()[variable]="NOT_FOUND"
    return(locals()[variable])

This function works fine but only if the input try statement yield a valid outcome, which defeats the entire purpose of the designed function.

For example, the following statement fails:

SHIPPING=try_except(i.find("span", {"id":"item-shipping-price-1"}).text, "SHIPPING")

---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-641-adff14bb2f4b> in <module>
----> 1 SHIPPING=try_except(i.find("span", {"id":"item-shipping-price-1"}).text, "SHIPPING")

AttributeError: 'NoneType' object has no attribute 'text'

Whereas the concept outside of the designed function works perfectly:

try:
    locals()["SHIPPING"]=i.find("span", {"id":"item-shipping-price-1"}).text
except:
    locals()["SHIPPING"]="NOT_FOUND"
    print(locals()["SHIPPING"])

prints: NOT_FOUND

Is there any way to define a function which does not validate the input statement and just proceeds with it as requested?

Solution

First: don’t do the thing with locals(). It’s completely unnecessary, since your function is returning the value (or at least trying to), and the caller is assigning it to the named variable anyway. This is orthogonal to your try/except problem anyway so I’ll say no more about it, other than to suggest that if in the future you ever feel the need to do something like this with locals() or globals(), you should almost definitely not do that thing.

The reason your function isn’t working is that you’re executing the code that raises the exception before you call the function, and therefore outside its try block. Your try_except function needs to take another function as its parameter, so that it can call it inside its try block:


def try_except(func):
    """Return result of calling func, or "NOT FOUND"."""
    try:
        return func()
    except:
        return "NOT FOUND"

and then call it like:

SHIPPING = try_except(lambda: i.find("span", {"id":"item-shipping-price-1"}).text)

Note that the lambda expression produces a function of zero arguments that will execute and return i.find("span", {"id":"item-shipping-price-1"}).text when it is called. By passing this function into try_except, you allow it to execute that code within the try block and handle the exception by returning its default "NOT FOUND" value.

Answered By – Samwise

Answer Checked By – Dawn Plyler (BugsFixing Volunteer)

Leave a Reply

Your email address will not be published.