dmb
dmb

Reputation: 298

Python - handle one exception in multiple ways

I have looked the usual search engines for this question. I have one kind of exception that need to be handled in different ways, due to different warnings that aren't periodic and don't have the same document layout, on a web site that I have automated a while back. The solution that I'm currently using is comment and decomment some part of the code when said warning appears on the site.

It always give me the ElementNotVisibleException, but having two excepts for the same error won't work as it will be handled by the first exception

While True:
    try:
        #some code
    except ElementNotVisibleException:
        #code to handle error1
    except ElementNotVisibleException:
        #code to handle error2 that will never be procesed

And nesting try...except block just seems too nasty. Because when the handling fails it will be due to other exception the NoSuchElementException, and using just except doesn't seems right too, because it can hide the real reason of why is failing

While True:
    try:
        #some code
        break
    except ElementNotVisibleException:
        try:
            #code to handle error1
            break
        except:
            #code to handle error2

So, my the question is, Is there any other way to handle on kind of exception on mutiple way, a more pythonic way?

Thanks

EDIT: to explain further what I'm intending to do.

Let's say the has to navigate some menus, but just before the menu some site alert appears, on this case we will call it warning1, warning2 and warning 3. In this scenario the script will break, due to the warning that makes invisible this menu.

Warning1: will have a continue button and is in the same frame.

Warning2: will be a pop over some overlay with a checkbox and a button(with differnt placeholder, id and xpath)

Warning3: will be nearly the same as warning1 but with different id, name and xpath.

But all of them will throw a ElementNotVisibleException. So all of them can't be handle in the same way and probably warningN will be appearing overtime(this script is old, like two years old) and I don't really want to spend too much time on it as I'm probably moving away from this in my career and want to leave it as readeable and explicit, for the chap that is going to take the position. So this guy can go an add some more code to overcome the new warning message.

EDIT2: The answer by @JeffC got the right idea and combining it with This answer by @CoryKramer to make it more aprochable for the new guy I've come up with this:

def not_visible_handler():
    ls_handlers = [warnin1_hanlder, warnin2_hanlder, warnin3_hanlder]

    def warnin1_hanlder():
        #code to handle warning 1
        return True

    def warnin2_hanlder():
        #code to handle warning 2
        return True

    def warnin3_hanlder():
        #code to handle warning 3
        return True

    for handler in ls_handlers:
        if handler() is True:
            break
    else: #this else belongs to the for
        raise Exception('No more Handlers for warning messages')


while True:
    try:
        #some code
        break
    except ElementNotVisibleException:
        not_visible_handler()

It's straight enough, so they won't touch actual working code and can add in more handlers in an easy fashion. Also with a little bit of work can be made into a module.

Edit3: The name of the functions in the list must not be a string, otherwise you will get TypeError: 'str' type is not callable

Upvotes: 0

Views: 127

Answers (1)

JeffC
JeffC

Reputation: 25744

I don't think you really need to catch multiple exceptions. The exception is the same, the cause is what is different. The cause is related to which warning is present. I would catch the exception and then proceed to determine which warning caused the exception. You can do this by locating the elements that are standard to warning1, warning2, and warning3. Once you find the element that is part of a particular warning, you can deal with it. The code below outlines this approach. I don't know the locators for the different scenarios so you will need to add the specific find method and locator.

While True:
    try:
        #some code
    except ElementNotVisibleException:
        #code to handle warning1
        if (len(driver.find_elements_by_*(warning1_locator)) > 0)
            #handle warning1 case

        #code to handle warning2
        if (len(driver.find_elements_by_*(warning2_locator)) > 0)
            #handle warning2 case

        #code to handle warning3
        if (len(driver.find_elements_by_*(warning3_locator)) > 0)
            #handle warning3 case

Upvotes: 2

Related Questions