Python Try with some Additional Logic - python

Hello I am trying to make 'try' only work under one condition:
try:
print "Downloading URL: ", url
contents = urllib2.urlopen(url).read()
except:
message = "No record retrieved."
print message
return None
I do not want the above code to work if the kwarg nodownload is True.
So I have tried the following:
try:
if nodownload:
print "Not downloading file!"
time.sleep(6)
raise
print "Downloading URL: ", url
contents = urllib2.urlopen(url).read()
except:
message = "No record retrieved."
print message
return None
The above always downloads no matter if the --nd argument is passed in the command line. The below always skips the file rather the argument is passed or not.
if not nodownload:
print "Not downloading file!"
time.sleep(6)
raise
print "Downloading URL: ", url
contents = urllib2.urlopen(url).read()
except:
message = "No record retrieved."
print message
return None
No download is input at the command line:
parser.add_argument('--nodownload', dest='nodownload', action='store_true',
help='This doesn't work for some reason')

You can use raise to cause an exception when you need to, thus making the try fail.

As others have mentioned, one can raise an exception.
Apart from using predefined exceptions, you may also use your own:
class BadFriend(Exception):
pass
class VirtualFriend(Exception):
pass
class DeadFriend(Exception):
pass
try:
name = raw_input("Tell me name of your friend: ")
if name in ["Elvis"]:
raise DeadFriend()
if name in ["Drunkie", "Monkey"]:
raise BadFriend()
if name in ["ET"]:
raise VirtualFriend()
print("It is nice, you have such a good friend.")
except BadFriend:
print("Better avoid bad friends.")
except VirtualFriend:
print("Whend did you shake hands with him last time?")
except DeadFriend:
print("I am very sorry to tell you, that...")
You can even pass some data via raised exception, but be careful not to abuse it too far (if
standard structures are working, use simpler ones).

Related

Two identical code snippets, one of them does not work. How come?

I am trying to rewrite some of my code into functions instead, but a problem has occurred, that does not make any sense for me. I will now show the two code snippets:
Code 1:
def get_isPrivateAccount(page_source):
try:
match = re.search(r'"isPrivateAccount":(.+?)', page_source)
if match:
isPrivateAccount = match.group(1)
except Exception as e:
print('Could not find the isPrivateAccount of the user. The following exception was raised:\n', e)
return isPrivateAccount
Code 2:
page_source = driver.page_source
match = re.search(r'"isPrivateAccount":(.+?)', page_source)
if match:
is_private = match.group(1)
else:
print('Match not found')
The first code gets the page_source = driver.page_source from another function that returns it, exactly the same way written.
How come the second code snippet works perfect and can find '"isPrivateAccount":false' and return 'f' without any problem as a string, but the first code snippet cannot and says that it is 'None'? Error code from first code snippet:
cannot access local variable 'isPrivateAccount' where it is not associated with a value
As the error traceback suggests if an exception occurs then the code execution jump to the exception block and then continue till the return were isPrivateAccount.. but it is only defined if no exception occur.
def get_isPrivateAccount(page_source):
try:
match = re.search(r'"isPrivateAccount":(.+?)', page_source)
if match:
return match.group(1)
except Exception as e:
print('Could not find the isPrivateAccount of the user. The following exception was raised:\n', e)
Notice that the try/except is a bit meaningless, use instead raise and/or a custom excpetion.
def get_isPrivateAccount(page_source):
match = re.search(r'"isPrivateAccount":(.+?)', 'bjkasfdjadas')
if match:
return match.group(1)
print(Exception('Could not find the isPrivateAccount of the user. The following exception was raised:'))
#raise Excpetion(...)
You are declaring and initializing isPrivateAccount inside the if statement. If there is no match, the variable will never be defined and the return statement throws an error as you cannot access a variable which does not exist.
You have to define the variable at the top of your function:
isPrivateAccount = None

Continue program even after assert fails

I want to continue even after the assert statement fails. Instead of saying "File not found" I would like to ignore it and continue my program. I am unable to figure out the syntax.
Overview of the script and problem faced :
This script is used for downloading pdf from urls which were written in a txt file. I had used assert to stop the program if the file wasn't found. It worked fine when all the urls in that txt file were working. The problem arose when there was a link which was dead and I didn't want the program to stop but instead continue to next link.
assert os.path.exists(of), "File not found at, " +str(of)
Program snippet :
for line in url_file:
stripped_line = line.split(',')
list_of_urls.append(stripped_line[2]+stripped_line[1])
driver.get(stripped_line[2]+stripped_line[1])
time.sleep(2)
of = download_dir+"/"+stripped_line[3]+".pdf"
fn = download_dir+"/"+stripped_line[0]+".pdf"
try:
assert os.path.exists(of), "File not found at, " +str(of)
except AssertionError:
pass
move(of, fn)
fns.append(stripped_line[0])
ofns.append(stripped_line[3])
status_file.write(stripped_line[0]+",File Downloaded\n")
url_file.close()
status_file.close()
driver.quit()
If you really want to use assert you can just us a try: except: block to catch the error thrown if the assertion is not True
try:
assert os.path.exists(of), "File not found at, " +str(of)
except AssertionError:
pass
However if your goal is just to print an error message if the file does not exist you can do:
if not os.path.exists(of):
print("File not found at, " +str(of))
if os.path.exists(of):
move(of, fn)
fns.append(stripped_line[0])
ofns.append(stripped_line[3])

how to properly use try/except/with inside functions and main

I am a relative python newbie and I am getting confused with how to properly handle exceptions. Apologies for the dumb question.
In my main() I iterate through a list of dates and for each date I call a function, which downloads a csv file from a public web server. I want to properly catch exceptions for obvious reasons but especially because I do not know when the files of interest will be available for download. My program will execute as part of a cron job and will attempt to download these files every 3 hours if available.
What I want is to download the first file in the list of dates and if that results in a 404 then the program shouldn't proceed to the next file because the assumption is if the oldest date in the list is not available then none of the others that come after it will be available either.
I have the following python pseudo code. I have try/except blocks inside the function that attempts to download the files but if an exception occurred inside the function how do I properly handle it in the main() so I can make decisions whether to proceed to the next date or not. The reason why I created a function to perform the download is because I want to re-use that code later on in the same main() block for other file types.
def main():
...
...
# datelist is a list of date objects
for date in datelist:
download_file(date)
def download_file(date):
date_string = str(date.year) + str(date.strftime('%m')) + str(date.strftime('%d'))
request = HTTP_WEB_PREFIX+ date_string + FILE_SUFFIX
try:
response = urllib2.urlopen(request)
except urllib2.HTTPError, e:
print "HTTPError = " + str(e)
except urllib2.URLError, e:
print "URLError = " + str(e)
except httplib.HTTPException, e:
print "HTTPException = " + str(e)
except IOError:
print "IOError = " + str(e)
except Exception:
import traceback
print "Generic exception: " + traceback.format_exc()
else:
print "No problem downloading %s - continue..." % (response)
try:
with open(TMP_DOWNLOAD_DIRECTORY + response, 'wb') as f:
except IOError:
print "IOError = " + str(e)
else:
f.write(response.read())
f.close()
The key concept here is, if you can fix the problem, you should trap the exception; if you can't, it's the caller's problem to deal with. In this case, the downloader can't fix things if the file isn't there, so it should bubble up its exceptions to the caller; the caller should know to stop the loop if there's an exception.
So let's move all the exception handling out of the function into the loop, and fix it so it craps out if there's a failure downloading the file, as the spec requires:
for date in datelist:
date_string = str(date.year) +
str(date.strftime('%m')) +
str(date.strftime('%d'))
try:
download_file(date_string)
except:
e = sys.exc_info()[0]
print ( "Error downloading for date %s: %s" % (date_string, e) )
break
download_file should now, unless you want to put in retries or something like that, simply not trap the exceptions at all. Since you've decoded the date as you like in the caller, that code can come out of download_file as well, giving the much simpler
def download_file(date_string):
request = HTTP_WEB_PREFIX + date_string + FILE_SUFFIX
response = urllib2.urlopen(request)
print "No problem downloading %s - continue..." % (response)
with open(TMP_DOWNLOAD_DIRECTORY + response, 'wb') as f:
f.write(response.read())
f.close()
I would suggest that the print statement is superfluous, but that if you really want it, using logger is a more flexible way forward, as that will allow you to turn it on or off as you prefer later by changing a config file instead of the code.
From my understanding of your question... you should just insert code into the except blocks that you want to execute when you encounter the particular exception. You don't have to print out the encountered error, you can do whatever you feel is necessary when it is raised... provide a popup box with information/options or otherwise direct your program to the next step. Your else section should isolate that portion, so it will only execute if none of your exceptions are raised.

Python hide error

Alright, I am fairly new to python and I am making a console witch will allow multiple features, one of those is to grab a page source and either print it on the page, or if they have another arg then name the file of that arg... The first arg would be the website url to grab the source from.
My imports are:
import os, urllib.request
This is my code:
def grab(command, args, argslist):
if args == "":
print("The " + command + " command wan't used correctly type help " + command + " for help...")
if args != "":
print("This may take a second...")
try:
argslistcheck = argslist[0]
if argslistcheck[0:7] != "http://":
argslist[0] = "http://" + argslist[0]
with urllib.request.urlopen(argslist[0]) as url:
source = url.read()
source = str(source, "utf-8")
except IndexError:
print("Couln't connect")
source = ""
try:
filesourcename = argslist[1] + ".txt"
filesourceopen = open(filesourcename, "w")
filesourceopen.write(source)
filesourceopen.close()
print("You can find the file save in " + os.getcwd() + " named " + argslist[1] + ".txt.")
except IndexError:
print(source)
Now while I will be ok with improving my code right now I'm focusing on the main point. Right now it works, I will improve the code later on, the only problem is that if the user inputs a fake website or a website page that doesn't exist then it returns lot's of errors. Yet if I change:
except IndexError:
print("Coulnd't connect")
source = ""
to just:
except:
print("Couldn't connect")
source = ""
Then it always says Couldn't connect...
Any help? I didn't put the rest of my code because I didn't think it would be useful, if you need it I can put it all.
The reason I titled this hide error is because it still works for some reason it just says that it was unable to connect, if the user types a second argument then it will save the source to the file he named.
try:
argslistcheck = argslist[0]
if argslistcheck[0:4] != "http://":
argslist[0] = "http://" + argslist[0]
with urllib.request.urlopen(argslist[0]) as url:
source = url.read()
source = str(source, "utf-8")
except IndexError:
print("Couln't connect")
source = ""
In that code block, the only thing that can raise an IndexError exception is the argslist[0]. This will happen if there is no element within that list. This is very likely not your problem.
Now if an invalid address is entered, urlopen will fail. But it will not raise an IndexError but rather an urllib.error.URLError or the more specialized urllib.error.HTTPError.
If you just write except IndexError you will only catch that error, but not the exception raised by the urlopen. If you want to catch those as well, you have to add another except case:
except IndexError:
print('Argument is missing')
except urllib.error.URLError:
print('Could not connect to the URL.')
The alternative is to just catch any exception by just not specifying any (this is what you did in your last code). Note that this is usually not recommended as it will hide any exceptions that occur which you might not have expected to ever happen; i.e. it will hide bugs. So if you know that there are only a few possible exceptions, just catch those and handle them explicitely.

I'm having a repeating try block issue

So i'm making a little app here, and I have try blocks (because I need to see if a file already exists or should be created). Although... my try block is repeating for some reason! I have ABSOLUTELY no idea why this is happening. Please help?
Also, the file is created fine :)
Code:
import sys
import time
Version = "V0.1"
def user():
PISBNdat = open("PISBN.dat", "w")
PISBNdat.write(Version)
cuser = raw_input("Please enter account username!")
for line in PISBNdat:
print "Test"
if cuser in line:
print("User already exists! Try again!")
user()
def start():
print "Hello and welcome to Plaz's PISBN!"
print "Opening file..."
time.sleep(0.8)
try:
fin = open("PISBN.dat", "r")
print "Success!"
fin.close()
user()
except:
time.sleep(0.5)
print "Did not recognize/find file!"
time.sleep(0.1)
print "Creating file!"
time.sleep(0.5)
try:
fout = open("PISBN.dat", "w")
print "Success!"
fout.close()
user()
except:
print "Failed!"
exit()
start()
And here's the output...:
Hello and welcome to Plaz's PISBN!
Opening file...
Did not recognize/find file!
Creating file!
Success!
Please enter account username! [This is what I entered: Plazmotech]
Failed!
Now obviously, since it said 'Failed!', it means its running my try block... because thats the only place it could output 'Failed!' So please help here!
Catch only the exceptions you want to handle. Note that printing "Failed!" and exiting is not handling an exception. Python's going to do that anyway, plus it's going to give you a buttload of information as to what happened, so why write extra code that does less and hides the cause of the problem?
As somebody (who just deleted his post) pointed out before, you call user() again in your user function, which is likely by mistake here.
I however believe your problems lie somewhere else. I assume you want "PISBN.dat" to contain a database where you look up for accounts. However, opening the file with only write permission will not help there. This causes your loop "for line in PISBNdat:" not working at all, so that the message "Test" did not appear.
It makes me think that "raw_input" failed and exception is caught. But as kindall pointed out, your code has some design flaws.
Here's an example of start() with correct try...except usage:
def start():
print "Hello and welcome to Plaz's PISBN!"
print "Opening file..."
time.sleep(0.8)
try: #try bloc contains minimum amount of code to catch the pertinent error.
f = open("PISBN.dat", "r")
print "Success!"
except IOError: #Only catch the exceptions you want to handle. IOError, in this case
f = None
if not f:
print "Did not recognize/find file!"
print "Creating file!"
try:
f = open("PISBN.dat", "w")
print "Success!"
except IOError:
print "Failed!"
exit()
f.close()
user() #Call user() after the file has been tested and/or created.

Categories