I am writing a python / selenium script that trawls a website to find elements then ultimately write these element values to a table.
When it identifies that the element does not exist, it throws the NoSuchElementException as expected.
I have been trying to figure out how to override this exception, to instead, populate the table with a default value e.g. 'No Value'.
Problem is, python seems to ignore whatever I try, only to throw the exception regardless, resulting in the script execution ending prior to the table being able to be populated.
Any ideas?
file_1.py
def getAttributes(self):
...
...
...
try:
score = box.find_element(By.CLASS_NAME, 'dealClass').get_attribute('innerHTML').strip()
if not score:
raise NoSuchElementException(f"Score does not currently exist for {name}, as of {datetime.today()}")
except NoSuchElementException as e:
print('Exception is: ', e)
# Writing remediating code here but it never seems to work..
raise
...
file_2.py
def reportResults(self):
...
searchResults = self.find_element(By.ID, 'search_results_table')
report = ReportSearchResults)
table = PrettyTable(field_names=["Name", "Price", "Score"])
table.align["Name"] = "l"
table.align["Price"] = "l"
table.align["Score"] = "r"
table.add_rows(report.getAttributes())
print(table)
...
When you catch the exception, you can "fix" it by giving score a value. There's no need to reraise the exception at that point; you've handled it, so let your script proceed as if nothing happened.
def getAttributes(self):
...
try:
score = box.find_element(By.CLASS_NAME, 'dealClass').get_attribute('innerHTML').strip()
if not score:
# You're going to catch it, and you don't really need
# a long message telling you what went wrong. *You* raised
# this one, and you know why, and you're going to fix it.
raise NoSuchElementException("no score")
except NoSuchElementException as e:
score = 'No value'
...
Related
I have this code structure:
#########file1.py#############
def newsCSVwriter(fileName):
try:
newsCleaner(fileName)
except Exception as e:
print "Exception: ", e
########file1.py#############
def newsCleaner(newsFile):
....
#########file2.py###########
try:
df1['newsFile'].apply(newsCSVwriter)
except Exception as e:
print "exception:",e
I want to write a csv that has a status column value of yes or no depending on whether newsCleaner(fileName) returns a value or exception. Should I implement the logic in file1 or file2? Also, an example will be great.
Assuming you don't actually need the returned value, in your newCSVWriter function do this:
try:
newsCleaner(fileName)
except:
return 'no'
else:
return 'yes'
How you structure your code in terms of files is dependant on what all of it does, but you've only posted part of it.
Stylistically I would rename them to something more informative than 'file1' and 'file2'. I would also have the function return a bool (True or False) instead, but that's up to you.
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
If I catch a KeyError, how can I tell what lookup failed?
def poijson2xml(location_node, POI_JSON):
try:
man_json = POI_JSON["FastestMan"]
woman_json = POI_JSON["FastestWoman"]
except KeyError:
# How can I tell what key ("FastestMan" or "FastestWoman") caused the error?
LogErrorMessage ("POIJSON2XML", "Can't find mandatory key in JSON")
Take the current exception (I used it as e in this case); then for a KeyError the first argument is the key that raised the exception. Therefore we can do:
except KeyError as e: # One would do it as 'KeyError, e:' in Python 2.
cause = e.args[0]
With that, you have the offending key stored in cause.
Expanding your sample code, your log might look like this:
def poijson2xml(location_node, POI_JSON):
try:
man_json = POI_JSON["FastestMan"]
woman_json = POI_JSON["FastestWoman"]
except KeyError as e:
LogErrorMessage ("POIJSON2XML", "Can't find mandatory key '"
e.args[0]
"' in JSON")
It should be noted that e.message works in Python 2 but not Python 3, so it shouldn't be used.
Not sure if you're using any modules to assist you - if the JSON is coming in as a dict, one can use dict.get() towards a useful end.
def POIJSON2DOM (location_node, POI_JSON):
man_JSON = POI_JSON.get("FastestMan", 'No Data for fastest man')
woman_JSON = POI_JSON.get("FastestWoman", 'No Data for fastest woman')
#work with the answers as you see fit
dict.get() takes two arguments - the first being the key you want, the second being the value to return if that key does not exist.
If you import the sys module you can get exception info with sys.exc_info()
like this:
def POIJSON2DOM (location_node, POI_JSON):
try:
man_JSON = POI_JSON["FastestMan"]
woman_JSON = POI_JSON["FastestWoman"]
except KeyError:
# you can inspect these variables for error information
err_type, err_value, err_traceback = sys.exc_info()
REDI.LogErrorMessage ("POIJSON2DOM", "Can't find mandatory key in JSON")
I have a function with a try catch block where I have:
def testfunction():
try:
good = myfunction()
return good
except ExceptionOne:
error="Error ExceptionOne".
return error
except ExceptionTwo:
error="Error ExceptionTwo".
return error
except ExceptionThree:
error="Error ExceptionThree".
return error
Is there a way such that I could structure this in such a way where have a single return statement for all the exceptions?
What about something like:
def testfunction():
try:
good = myfunction() # or `return myfunction()` if the case is actually this simple
except (ExceptionOne, ExceptionTwo, ExceptionThree) as err:
error = 'Error %s' % err.__class__.__name__
return error
return good
Of course, I'm not exactly sure what the purpose of this is. Why not just let the exception propogate and handle it higher up? As it is, you need logic to check the return value to see if it's good or not anyway, I think it would be cleaner if that logic was bound up in exception handling rather than in type checking or string value checking ...