Reputation: 298
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
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