I'm trying to write a while loop to check for errors during an automated login. I want it to run through the login and if there is an error then refresh the page and start again. When I try to use the exception InvalidSelectorException: I get an undefined error. Is there another way I should write this? Or a different exception I should use?
while True:
try:
loginButton = browser.find_element_by_xpath('//*[#id="global-header"]/div[2]/ul/li[2]/a')
loginButton.click()
time.sleep(3)
iframe = browser.switch_to.frame('disneyid-iframe')
Username = browser.find_element_by_xpath('//*[#id="did-ui"]/div/div/section/section/form/section/')
Username.send_keys(usernameStr)
time.sleep(3)
password = browser.find_element_by_xpath('//*[#id="did-ui"]/div/div/section/section/form/section/div[2]/div/label/span[2]/input')
password.send_keys(passwordStr)
time.sleep(3)
nextButton = browser.find_element_by_xpath('//*[#id="did-ui"]/div/div/section/section/form/section/div[3]/button[2]')
nextButton.click()
break
except:
browser.refresh()
the exception clause with no exception fixed it.
You can also use the except statement with no exceptions defined as follows −
try:
You do your operations here;
......................
except:
If there is any exception, then execute this block.
......................
else:
If there is no exception then execute this block.
Related
In python I have a function called func() which could raise NoSuchElementException:
I'm trying to call it with input1 if not correct call it with input2 else give up.
Is there any better way to write this code for clarity:
submit_button = None
try:
submit_button = func(input1)
except NoSuchElementException:
try:
submit_button = func(input2)
except NoSuchElementException:
pass
you can do something like:
for i in [input1, input2]:
try:
submit_button = func(i)
break
except NoSuchElementException:
print(f"Input {i} failed")
else:
print("None of the options worked")
If the first input doesn't throw an exception you break the loop, otherwise you keep in the loop and try the second input.
This way you can try as many inputs as you want, just add them into the list
The else at the end executes if you never broke the loop, which means none of the options worked
This works well if you want to try several inputs and treat them equally. For only two inputs your code looks readable enough to me. (try this, if it doesn't work try that)
Just another option...
from contextlib import suppress
submit_button = None
for i in input1, input2:
with suppress(NoSuchElementException):
submit_button = func(i)
break
I'm using try and except indentation. How should I indent after I the try and except code.
Example:
try:
for elem in
browser.find_elements_by_xpath('/html/body/form[2]/table/tbody/tr[1]/td[1]/select/option'):
elem.click()
except StaleElementReferenceException:
for elem in browser.find_elements_by_xpath('/html/body/form[2]/table/tbody/tr[1]/td[1]/select/option'):
elem.click()
for ele in browser.find_elements_by_xpath('/html/body/form[2]/table/tbody/tr[1]/td[2]/table/tbody/tr[1]/td[1]/select/option'):
ele.click()
I'm using "try and except" because I keep getting an error of StaleElementReferenceException. The only thing is that I need to use try and except multiple times in loops.
It seems you did right, the next line after the except that is out of the except should be indented at the same level. So:
try:
bla()
except X as y:
foo()
bar()
Note the additional blank line before bar to keep the code more readable.
Also, in the try block you can move the call browser.find_elements_by_xpath to a variable assignment before, and that way keep your code a bit more readable.
e.g.
all_options = browser.find_elements_by_xpath(
'/html/body/form[2]/table/tbody/tr[1]/td[1]/select/option')
for option in all_options:
option.click()
In case you want to have another try except wrapping the other loop in the except, you can do that nicely in multiple ways. My recommendation is to wrap the loop in a function that will "convert" the exception to a return value:
def click_all_options(path):
try:
for option in browser.find_elements_by_xpath(path):
option.click()
return True
except StaleElementReferenceException:
return False
and in the code:
select1 = '/html/body/form[2]/table/tbody/tr[1]/td[1]/select/option'
select2 = '/html/body/form[2]/table/tbody/tr[1]/td[2]/table/tbody/tr[1]/td[1]/select/option'
result = click_all_options(select1):
if not result:
click_all_options(select2):
I am trying to verify if a row is displayed or not. I am using python and Selenium. Here is what I have tried so far
try:
row = self.driver.find_element_by_xpath(<row6>).is_displayed()
if row is False:
print("button is not displayed. Test is passed")
else:
do stuff
except:
NoSuchElementException
I am trying to achieve the following:
Page #1 will only display a button if Page #2 has row < 6.
I still have logic to write for the condition -> if row is False: . However, it should atleast print the string if it is false.
At the moment, the else: in my code is not working. There is no error displays but try: exits at the NoSuchElementException.
UPDATE: I have also tried the following code where I verify if button is displayed on page #1, go to the page #2 and validate if row6 is present. That works if button is displayed. If button is not displayed, it throws an error :NoSuchElementException: Message: Unable to locate element:
try:
button = self.driver.find_element_by_xpath(PATH)
if button.is_displayed():
do stuff
row = self.driver.find_element_by_xpath(<row6>)
if row.is_displayed():
do stuff
else:
do stuff
except:
button = self.driver.find_element_by_xpath("PATH").is_displayed()
if button is False:
print("button is hidden. Test is passed")
Any suggestion on how I can make this work??
I don't know Selenium, but it sounds like there may be multiple exceptions here, not all of the same type, and not where you might expect them to happen. For instance, everything is fine when row.is_displayed() evaluates to True, but an exception is thrown otherwise - This indicates to me that row might be None or some other unexpected result. I've taken a cursory look at the docs but I couldn't see right away.
Anyway - to debug this, try putting different sections of your code into try-except blocks:
try:
button = self.driver.find_element_by_xpath(PATH)
if button.is_displayed():
do stuff
try:
row = self.driver.find_element_by_xpath(<row6>)
except: # <-- Better if you test against a specific Exception!
print(" something is wrong with row! ")
try:
if row.is_displayed():
do stuff
else:
do stuff
except: # <-- Better if you test against a specific Exception!
print( " something is wrong with using row!" )
except: # <-- Better if you test against a specific Exception!
button = self.driver.find_element_by_xpath("PATH").is_displayed()
if button is False:
print("button is hidden. Test is passed")
Also, try to put a minimum amount of code inside each try-except, so that you know where the exception is coming from.
Maybe there's no hidden row6 to be found and an exception is raised.
The syntax of your except is wrong: as it is, it will catch all exceptions and then just do nothing with the NoSuchElementException object.
Did you mean:
except NoSuchElementException:
#do something when no row6 found
am developing a python application . I have validated customer id from database. Means if the entered custid is present in database, i am raising an exception. In exception class i am printing the message . So far it is printing the message. But i am not sure how to get control back to the statement where i am taking the input.
main app
Custid=input("enter custid)
Validate_custid(Custid)
Print(Custid)
validate_custid module
From connections import cursor
From customExceptions import invalidcustidException
Def validate_custid(custid):
Cursor.execute("select count(custid) from customer where custid=:custid",{"custid":custid})
For row in cursor:
Count=row[0]
If Count==0:
Raise invalidcustidException
So far its printing the message in exception.now i want my program to take custid as input whenever this exception occurs. The process should iterate until user enters valid custid.
You should use a try-except block with else statement:
while True:
custid = input('Input custom Id: ')
try:
# Put your code that may be throw an exception here
validate_custid(custid)
except InvalidcustidException as err:
# Handle the exception here
print(err.strerror)
continue # start a new loop
else:
# The part of code that will execute when no exceptions thrown
print('Your custom id {} is valid.'.format(custid))
break # escape the while loop
Take a look at here: https://docs.python.org/3.4/tutorial/errors.html#handling-exceptions
You'll want a try except block.
try:
# portion of code that may throw exception
except invalidcuspidError:
# stuff you want to do when exception thrown
See https://docs.python.org/2/tutorial/errors.html for more.
What you are trying to do is called exception handling. I think the Python docs explain this better than me, so here you go: https://docs.python.org/2/tutorial/errors.html#handling-exceptions
In my application users enter a url and I try to open the link and get the title of the page. But I realized that there can be many different kinds of errors, including unicode characters or newlines in titles and AttributeError and IOError. I first tried to catch each error, but now in case of a url fetch error I want to redirect to an error page where the user will enter the title manually. How do I catch all possible errors? This is the code I have now:
title = "title"
try:
soup = BeautifulSoup.BeautifulSoup(urllib.urlopen(url))
title = str(soup.html.head.title.string)
if title == "404 Not Found":
self.redirect("/urlparseerror")
elif title == "403 - Forbidden":
self.redirect("/urlparseerror")
else:
title = str(soup.html.head.title.string).lstrip("\r\n").rstrip("\r\n")
except UnicodeDecodeError:
self.redirect("/urlparseerror?error=UnicodeDecodeError")
except AttributeError:
self.redirect("/urlparseerror?error=AttributeError")
#https url:
except IOError:
self.redirect("/urlparseerror?error=IOError")
#I tried this else clause to catch any other error
#but it does not work
#this is executed when none of the errors above is true:
#
#else:
# self.redirect("/urlparseerror?error=some-unknown-error-caught-by-else")
UPDATE
As suggested by #Wooble in the comments I added try...except while writing the title to database:
try:
new_item = Main(
....
title = unicode(title, "utf-8"))
new_item.put()
except UnicodeDecodeError:
self.redirect("/urlparseerror?error=UnicodeDecodeError")
This works. Although the out-of-range character —is still in title according to the logging info:
***title: 7.2. re — Regular expression operations — Python v2.7.1 documentation**
Do you know why?
You can use except without specifying any type to catch all exceptions.
From the python docs http://docs.python.org/tutorial/errors.html:
import sys
try:
f = open('myfile.txt')
s = f.readline()
i = int(s.strip())
except IOError as (errno, strerror):
print "I/O error({0}): {1}".format(errno, strerror)
except ValueError:
print "Could not convert data to an integer."
except:
print "Unexpected error:", sys.exc_info()[0]
raise
The last except will catch any exception that has not been caught before (i.e. a Exception which is not of IOError or ValueError.)
You can use the top level exception type Exception, which will catch any exception that has not been caught before.
http://docs.python.org/library/exceptions.html#exception-hierarchy
try:
soup = BeautifulSoup.BeautifulSoup(urllib.urlopen(url))
title = str(soup.html.head.title.string)
if title == "404 Not Found":
self.redirect("/urlparseerror")
elif title == "403 - Forbidden":
self.redirect("/urlparseerror")
else:
title = str(soup.html.head.title.string).lstrip("\r\n").rstrip("\r\n")
except UnicodeDecodeError:
self.redirect("/urlparseerror?error=UnicodeDecodeError")
except AttributeError:
self.redirect("/urlparseerror?error=AttributeError")
#https url:
except IOError:
self.redirect("/urlparseerror?error=IOError")
except Exception, ex:
print "Exception caught: %s" % ex.__class__.__name__