Python try / except / else loop does both the try and else actions - python

I'm running a Python script to post a Tweet if the length is short enough with an exception for errors and an else statement for messages that are too long.
When I run this, it posts the Tweet and still gives the Tweet too long message. Any idea why that is happening and how to make it work as intended?
if len(tweet_text) <= (280-6):
try:
twitter = Twython(CONSUMER_KEY,CONSUMER_SECRET,ACCESS_KEY,ACCESS_SECRET)
twitter.update_status(status=tweet_text)
except TwythonError as error:
print(error)
else:
print("Tweet too Long. Please try again.")

The first string is checking the length of the tweet. Move the else four spaces back. Because try/except construction can be try/except/else construction

From the docs:
The try … except statement has an optional else clause, which, when present, must follow all except clauses. It is useful for code that must be executed if the try clause does not raise an exception. (emphasis added)
Spaces/Tabs matter in Python.
What your snippet says in common English
is "Try to post the tweet, unless there's an error, then print the error. If there's not an error, print 'Tweet too long. Please try again.'"
What you want is:
if len(tweet_text) <= (280-6):
try:
twitter = Twython(CONSUMER_KEY,CONSUMER_SECRET,ACCESS_KEY,ACCESS_SECRET)
twitter.update_status(status=tweet_text)
except TwythonError as error:
print(error)
else:
print("Tweet too Long. Please try again.")

Related

How do I handle mySQL exceptions in Python?

I would like to ask how do I handle MySQL exceptions in Python. Basically, my program asks for the number of descriptions they would like to enter and I have an if statement to check that the number they have entered does not exceed 10. However, the column in my database called "Description" only allows 100 characters. Thus, the total number of chars entered by the user cannot exceed 100 chars, however, I cannot catch the exception. I have looked at multiple online resources such as importing "mysql.connector" and tried catching the DataError exception but it is still not working. I also tried specifying the exact exception but it still gives the same error when I try to test entering characters more than 100. Does anyone know any possible ways I can address this?
My end goal is to print out the cause of the error to the user and inform them that they cannot enter more than 100 characters and prevent the program from stopping abruptly. Thank you.
Below are some snapshots of my code and the exception I am trying to catch.
My Code
Exception encountered and trying to catch
The exception you need to catch is in the last line of your "Exception encountered and trying to catch" image.
The exception is of type "mysql.connector.error.DataError".
In your first image you are catching "mysql.connector.DataError".
You are missing an "error." in between.
Your code seems to be incomplete, so I am assuming this is what you are looking for. From the MySQL Connector/Python Developer Guide, section 10.12.2 errors.Error Exception, I propose the following solution:
import mysql.connector
...
while True:
try:
number_of_description = int(input("Enter the number of descriptions you would like to give the item: "))
except ValueError:
print("You cannot enter a non-number value. Please try again.")
except mysql.connector.Error as err:
if err.errno == 1406:
print('DataError: This exception is raised when there were problems with the data.')
continue

How to handle 2 different errors in Python 3, both of which are ValueError

I have a list of twitter usernames that I use to get tweets. During the process, I face 2 main errors:
CRITICAL:root:twint.get:User:'user'
raise ValueError("Cannot find twitter account with name = " + self.config.Username)
ValueError: Cannot find twitter account with name = blablabla
CRITICAL:root:twint.get:User:'data'
raise ValueError("Cannot find twitter account with name = " + self.config.Username)
ValueError: Cannot find twitter account with name = blablabla
The first one happens when the username is incorrect and I don't mind passing the error. However, the second one I believe is due to connection timeout or something similar, because whenever I get that error, I stop the script for 3-4 minutes and continue and it goes on as usual.
Therefore, I want to catch the 2nd error and handle it with sleep(). The problem is, if I do this it will sleep through incorrect username error as well and that's a waste of time:
try:
some code
except ValueError:
sleep(200)
How can I make it sleep only if the 2nd error happens?

Try and except whilst trying to writerow in Python

I have the following code that is throwing up an out of range error on the barcode looping section of the below code.
for each in data['articles']:
f.writerow([each['local']['name'],
each['information'][0]['barcodes'][0]['barcode']])
I wrote a try and except to catch and handle when a barcode is not present within the json I am parsing and this worked perfectly during testing using the print function however I have been having some trouble getting the try and except to work whilst trying to writerow to a csv file.
Does anyone have any suggestions or another method I could try to get this to work.
My try and accept which worked when testing using print was as follows:
for each in data['articles']:
print(each['local']['name'])
try:
print(each['information'][0]['barcodes'][0]['barcode'])
except:
"none"
Any help is much appreciated!
As komatiraju032 points out, one way of doing this is via get(), although if there are different elements of the dictionary that might have empty/incorrect values, it might get unwieldy to provide a default for each one. To do this via a try/except you might do:
for each in data['articles']:
row = [each['local']['name']]
try:
row.append(each['information'][0]['barcodes'][0]['barcode'])
except (IndexError, KeyError):
row.append("none")
f.writerow(row)
This will give you that "none" replacement value regardless of which of those lists/dicts is missing the requested index/key, since any of those lookups might raise but they'll all end up at the same except.
Use dict.get() method. It will return None if key not exist
res = each['information'][0]['barcodes'][0].get('barcode')

How to ignore an IndexError on Python

I'm trying to write a script that will go through a list of urls and scrape the web page connected to that url and save the contents to a text file. Unfortunately, a few random urls lead to a page that isn't formatted in the same way and that gets me an IndexError. How do I write a script that will just skip the IndexError and move onto the next URL? I tried the code below but just get syntax errors. Thank you so much in advance for your help.
from bs4 import BeautifulSoup, SoupStrainer
import urllib2
import io
import os
import re
urlfile = open("dailynewsurls.txt",'r') # read one line at a time until end of file
for url in urlfile:
try:
page = urllib2.urlopen(url)
pagecontent = page.read() # get a file-like object at this url
soup = BeautifulSoup(pagecontent)
title = soup.find_all('title')
article = soup.find_all('article')
title = str(title[0].get_text().encode('utf-8'))
except IndexError:
return None
article = str(article[0].get_text().encode('utf-8'))
except IndexError:
return None
outfile = open(output_files_pathname + new_filename,'w')
outfile.write(title)
outfile.write("\n")
outfile.write(article)
outfile.close()
print "%r added as a text file" % title
print "All done."
The error I get is:
File "dailynews.py", line 39
except IndexError:
^
SyntaxError: invalid syntax
you would do something like:
try:
# the code that can cause the error
except IndexError: # catch the error
pass # pass will basically ignore it
# and execution will continue on to whatever comes
# after the try/except block
If you're in a loop, you could use continue instead of pass.
continue will immediately jump to the next iteration of the loop,
regardless of whether there was more code to execute in the iteration
it jumps from. sys.exit(0) would end the program.
Do the following:
except IndexError:
pass
And as suggested by another user, remove the another except IndexError.
When I run your actual program, either the original version or the edited one, in either Python 2.5 or 2.7, the syntax error I get is:
SyntaxError: 'return' outside function
And the meaning of that should be pretty obvious: You can't return from a function if you aren't in a function. If you want to "return" from the entire program, you can do that with exit:
import sys
# ...
except IndexError:
sys.exit()
(Note that you can give a value to exit, but it has to be a small integer, not an arbitrary Python value. Most shells have some way to use that return value, normally expecting 0 to mean success, a positive number to mean an error.)
In your updated version, if you fix that (whether by moving this whole thing into a function and then calling it, or by using exit instead of return) you will get an IndentationError. The lines starting with outfile = … have to be either indented to the same level as the return None above (in which case they're part of the except clause, and will never get run), or dedented back to the same level as the try and except lines (in which case they will always run, unless you've done a continue, return, break, exit, unhandled raise, etc.).
If you fix that, there are no more syntax errors in the code you showed us.
I suspect that your edited code still isn't your real code, and you may have other syntax errors in your real code. One common hard-to-diagnose error is a missing ) (or, less often, ] or }) at the end of a line, which usually causes the next line to report a SyntaxError, often at some odd location like a colon that looks (and would be, without the previous line) perfectly valid. But without seeing your real code (or, better, a real verifiable example), it's impossible to diagnose any further.
That being said, I don't think you want to return (or exit) here at all. You're trying to continue on to the next iteration of the loop. You do that with the continue statement. The return statement breaks out of the loop, and the entire function, which means none of the remaining URLs will ever get processed.
Finally, while it's not illegal, it's pointless to have extra statements after a return, continue, etc., because those statements can never get run. And similarly, while it's not illegal to have two except clauses with the same exception, it's pointless; the second one can only run in the case where the exception isn't an IndexError but is an IndexError, which means never.
I suspect you may have wanted a separate try/except around each of the two indexing statements, instead of one around the entire loop. While that isn't at all necessary here, it can sometimes make things clearer. If that's what you're going for, you want to write it like this:
page = urllib2.urlopen(url)
pagecontent = page.read() # get a file-like object at this url
soup = BeautifulSoup(pagecontent)
title = soup.find_all('title')
article = soup.find_all('article')
try:
title = str(title[0].get_text().encode('utf-8'))
except IndexError:
continue
try:
article = str(article[0].get_text().encode('utf-8'))
except IndexError:
return continue
outfile = open(output_files_pathname + new_filename,'w')
outfile.write(title)
outfile.write("\n")
outfile.write(article)
outfile.close()
print "%r added as a text file" % title
You cant "return"
except IndexError:
return None
article = str(article[0].get_text().encode('utf-8'))
this is not a function call
use a "pass" or "break" or "continue"
EDIT
try this
try:
page = urllib2.urlopen(url)
pagecontent = page.read() # get a file-like object at this url
soup = BeautifulSoup(pagecontent)
title = soup.find_all('title')
article = soup.find_all('article')
title = str(title[0].get_text().encode('utf-8'))
except IndexError:
try:
article = str(article[0].get_text().encode('utf-8'))
except IndexError:
continue

Try / except syntax in Python with two of the same exceptions

I am checking emails against two lists -- a list of domains and a list of individual emails.
How would I construct the following try statement --
Try: 'email in email_list'
Except DoesNotExist: 'domain in domain list' # if email not found
Except DoesNotExist: 'print error message' # if both email and domain not found
What syntax do I need to use to construct this statement?
It sounds like you're looking for something like:
if email in email_list:
# do something with email
elif domain in domain_list:
# do something with domain
else:
print "neither email nor domain found"
There is probably no need for exceptions in this case.
Why don't define two exceptions: DomainDoesNotExists, EmailDomainDoesNotExists ?
try:
'email in email_list'
except DomainDoesNotExists:
...
except EmailDomainDoesNotExists:
...
There is no way to do what you want with only one Exception type (e.g. DoesNotExists).
But you better listen to #Greg Hewgill, in this case you don't need exceptions
It is hard to know what you are trying to do. Your capitalizations are a problem. When you catch exceptions, proceed from the most specific to the general. The first handler block handles the exception and puts you out of the try-except progression.
try:
yourEmailRoutine
except DomainDoesNotExist:
##code to be carried out if domain does not exist...
print "The domain %s does not exist." % yourDomainName
Since emails are often malformed, you might want to use Greg's suggestion to deal with this in an if-elif-else progression.

Categories

Resources