There are many at times we write code inside try: and except: block in Django. But my confusion is what to write inside exception: block or how to know what is the exact error and raise it.
For ex: In this particular case I am invoking an utility function from my views.py, and I have written like this.
try:
res = process_my_data(request, name, email)
except:
import sys
print sys.exc_value
Inside the process_my_data() definition I am doing some kind of DB operations. If it fails, and comes to except block what should I write here. I am not sure what to write that is why written print sys.exc_value
I think the biggest question you have to ask yourself is "why am I writing this as a try except in the first place?" Do you know that what is inside the try is capable of throwing an exception? If the answer to that is yes, then surely you know what type of exception to catch. In this instance it seems like it depends on what backend DB library you are using. Look up the documentation for the one you're using. From there it's really up to you what you want to do within the except - how do you want your program to behave if an exception is thrown? At the absolute minimum I would catch a general exception and print the output to the console with something like this:
except Exception, e:
message = str(e)
print (message)
Related
I have a Python script running on a schedule and I have set up a try/except block to catch all exceptions and email me the exception message so that I can be made aware that something has gone wrong.
I am observing some odd behavior. For every execution of my script, an Exception is being caught where the message is simply:
93
This content is the same when I print it to the console as well.
When I remove the try/except block, there aren't any exceptions being thrown by my code. Does anyone know why the presence of the try/except blocks are causing exceptions and why it is just returning digits?
try:
#do something
except Exception as ex:
s = smtplib.SMTP('000.000.000.000',25)
s.starttls()
s.sendmail('email#email.com', 'email#email.com', 'General Exception in final_parse method ' + str(ex.message))
print str(ex.message)
s.quit()
It depends on what you're doing in your try. The exception is created and raised in that code. It is possible to set an exception's message to 93, or to anything else.
Try evaluating the entire exception in your debugger, or stepping through the code you're running in try until you get the the exception, and look at the context in which it is created/raised. This will at least give you an idea of what the code/module was doing when it failed.
My guess is that the code running in try isn't well written or maintained. Try a different module, or post more details about it here.
Update:
If your stack trace is giving you KeyError, then the code you're executing is throwing a KeyError exception that isn't handled by an except block deeper down in the code, which would mean it's either poorly written or being poorly used. The issue is most likely within your 'do something'
Rather than use smtplib.SMTP you should use Yagmail. It's easier to use:
import yagmail
yag = yagmail.SMTP(username, password)
yag.send(emailto, subject = "I now can send an attachment", contents = fileToSend)
In Python, is there any (proper) way to change the the default exception handling behaviour so that any uncaught exception will terminate/exit the program?
I don't want to wrap the entire program in a generic try-except block:
try:
// write code here
except Exception:
sys.exit(1)
For those asking for more specificity and/or claiming this is already the case, it's my understanding that not all Python exceptions are system-exiting: docs
Edit: It looks like I have forked processes complicating matters so won't be posting any specific details about my own mess.
If you're looking for an answer to the original question, Dmitry's comment is interesting and useful, references the 2nd answer to this question
You can use Specific exception instead of Exception because Exception is a Base class for all exceptions. For more details refer Exception tutorial
You can write your script like this-
try:
# write code here
except OverflowError:
raise SystemExit
except ArithmeticError:
sys.exit()
except IOError:
quit()
Try this different approaches to find what is exactly you are missing.
Edit 1 - Maintain Program Execution
In order to maintain your program execution try this one-
consider error_handler function is raising SystemExit exception then In your main method you need to add below code so you can maintain your program execution.
try:
error_handler()
except SystemExit:
print "sys.exit was called but I'm proceeding anyway (so there!-)."
Python newbie here and am running into some weird behavior in my code.
I am trying to write some data to a file. I print the length of the data to be about 50k before I call the following block of code. The data is a pdf file I got over the internet. And its a valid pdf.
When I call the function F() described below, I get the exception message printed in function F and not in the actual place it fails.
In the code below, in the function write_to_disk() I see the second print and the execution directly jumps to the exception handler in the calling function F(). I cannot figure out why this is happening. On disk I see the file is created but the size is 0.
Can some look at the code below and may be guess what could be happening?
If I am catching exceptions in the write_to_disk() function how is it possible for it to jump out of the function completely?
EDIT: Thanks for kobejohn, turns out the excetion object does not have a errno variable. Getting rid of it made the print appear. But the bigger problem still exists. I see a failure with no way to find out why its failing. How do I get the error message here?
def write_to_disk(self, pathToWrite, pdfFileData):
try:
print 'Here `1.1'
fd = open(pathToWrite, "w+")
print 'Here `2.1'
fd.write(pdfFileData)
print 'Here 3.1'
fd.close()
except Exception as e:
print 'file cannot be opened ' + pathToWrite + e.errno
This function is inturn called by another function F which is like this -
def F(self, url):
pathWrite = get_path_to_use()
pdfData = get_pdf_data(url)
try:
writetodisk(pathToWrite, pdfData)
except Exception as e:
print 'Did I jump directly to here?' + e.errno
Here is the out put of the program. I did not think it will add anything because I see nothing if any use. In fact I get the same output even when running it in pdb.
Here `1.1
Here `2.1
Did I jump directly to here?
Your first exception handler tries to build a string by concatenating another string and an int (e.errno) which causes it (the print statement) to throw an exception itself (which is then caught by the outer exception handler).
It's just bubbling as we mentioned in the comments and Alexander said. Use this code to see how it can work (no errors, but that was just a nasty surprise you got with exceptions).
def f(url):
path_to_write = 'test.dat'
pdf_data = 'asdf'
try:
write_to_disk(path_to_write, pdf_data)
except Exception as e:
print 'Did I jump directly to here?\n' + str(e)
def write_to_disk(path_to_write, pdf_data):
try:
print 'Here `1.1'
with open(path_to_write, "w+") as fd:
print 'Here `2.1'
fd.write(pdf_data)
except Exception as e:
print 'file cannot be opened ' + path_to_write
f('fake_url')
Some areas to make your code safer / more standard:
do as little as possible inside a try block. try to isolate the code that you are worried might raise an error
same rule for the except block. don't do anything strange there.
as someone else mentioned, using a with block is a more standard and readable way to work with a file.
other minor things with function and variable names you can see where I have changed things in the code above. google PEP 8 for more.
I have noticed me writing try-except clauses like the following very much in the past. The main reason for this is to write less code.
class Synchronizer(object):
# ...
def _assert_dir(self, dirname, argname, argnum):
""" *Private*. Raises OSError if the passed string does not point
to an existing directory on the file-system. """
if not os.path.isdir(dirname):
message = 'passed `%s` argument (%d) does not point to a ' \
'directory on the file-system.'
raise OSError(message % (argname, argnum))
def synchronize(self, source_dir, dest_dir, database):
# Ensure the passed directories do exist.
try:
self._assert_dir(source_dir, 'source_dir', 2)
self._assert_dir(dest_dir, 'dest_dir', 3)
except OSError:
raise
# ...
I was doing it this way, because otherwise I would've needed to write
class Synchronizer(object):
# ...
def synchronize(self, source_dir, dest_dir, database):
# Ensure the passed directories do exist.
if not os.path.isdir(source_dir):
message = 'passed `source_dir` argument (2) does not point to a ' \
'directory on the file-system.'
raise OSError(message)
if not os.path.isdir(dest_dir):
message = 'passed `dest_dir` argument (3) does not point to a ' \
'directory on the file-system.'
raise OSError(message)
# ...
I actually like the idea of writing methods doing check-and-raise operations, but I see one big disadvantage: Readability. Especially for editors that do code-folding, the try statement is not very much telling the reader what happens inside of it, while if not os.path.isdir(source_dir) is quite a good hint.
IMHO the try-except clause is required because it would confuse the catcher of the exception (reader of the traceback) where the exception comes from.
What do you think about this design? Is it awful, great or confusing to you? Or do you have any ideas on how to improve the situation?
There are two questions that I ask myself before using try for handling exceptional conditions and if the answer is YES to both, only then I will try to handle the exception.
Q1. Is this truly an exception scenario? I do not want to execute try blocks if the condition occurs 90% of the time. It is better to use if - else in such a case.
Q2. Can I recover from the error? It makes little sense to handle the exception if I cannot recover from it. It's better to propagate it to a higher level which happens automatically without me having to write extra code.
The code posted by you does not do anything to recover if the directory does not exist and it does not appear that you can do much about it. Why not let the error propagate to a higher level? Why do you even need a try block there?
This depends upon your requirement..
If you want to catch some exception, and continue with the code in your method, then you should use the 2nd scenario. Have yout try-except block inside your method.
def function():
try:
raise IOError
except IOError e:
// Handle
//continue with reset of the function
print "This will get printed"
function()
But if you want to handle all the exception at one place, with specific action for specific type, or you just want to halt your function, if one exception is raised, you can better handle them outside your function: -
def function():
raise IOError
// subsequent code Will not execute
print "This will not get printed"
try:
function()
except IOError e:
// Handle IOError
except EOFError e1:
// Handle EOF Error
By using the 2nd way, you are actually increasing the chance of some of your codes not getting executed. In general, your try-except block should be small. They should be separated for handling exception at different points and not all the exceptions should be handled at one place.
As far as I'm concerned, I generally like to minimize my try-except block as much as possible. That way I know where exactly my exception was raised.
I find I've been confused by the problem that when I needn't to use try..except.For last few days it was used in almost every function I defined which I think maybe a bad practice.For example:
class mongodb(object):
def getRecords(self,tname,conditions=''):
try:
col = eval("self.db.%s" %tname)
recs = col.find(condition)
return recs
except Exception,e:
#here make some error log with e.message
What I thought is ,exceptions may be raised everywhere and I have to use try to get them.
And my question is,is it a good practice to use it everywhere when defining functions?If not are there any principles for it?Help would be appreciated!
Regards
That may not be the best thing to do. Whole point of exceptions is that you can catch them on very different level than it's raised. It's best to handle them in the place where you have enough information to make something useful with them (that is very application and context dependent).
For example code below can throw IOError("[Errno 2] No such file or directory"):
def read_data(filename):
return open(filename).read()
In that function you don't have enough information to do something with it, but in place where you actually using this function, in case of such exception, you may decide to try different filename or display error to the user, or something else:
try:
data = read_data('data-file.txt')
except IOError:
data = read_data('another-data-file.txt')
# or
show_error_message("Data file was not found.")
# or something else
This (catching all possible exceptions very broadly) is indeed considered bad practice. You'll mask the real reason for the exception.
Catch only 'explicitely named' types of exceptions (which you expect to happen and you can/will handle gracefully). Let the rest (unexpected ones) bubble as they should.
You can log these (uncaught) exceptions (globally) by overriding sys.excepthook:
import sys
import traceback
# ...
def my_uncaught_exception_hook(exc_type, exc_value, exc_traceback):
msg_exc = "".join( \
traceback.format_exception(exc_type, exc_value, exc_traceback) )
# ... log here...
sys.excepthook = my_uncaught_exception_hook # our uncaught exception hook
You must find a balance between several goals:
An application should recover from as many errors as possible by itself.
An application should report all unrecoverable errors with enough detail to fix the cause of the problem.
Errors can happen everywhere but you don't want to pollute your code with all the error handling code.
Applications shouldn't crash
To solve #3, you can use an exception hook. All unhandled exceptions will cause the current transaction to abort. Catch them at the highest level, roll back the transaction (so the database doesn't become inconsistent) and either throw them again or swallow them (so the app doesn't crash). You should use decorators for this. This solves #4 and #1.
The solution for #2 is experience. You will learn with time what information you need to solve problems. The hard part is to still have the information when an error happens. One solution is to add debug logging calls in the low level methods.
Another solution is a dictionary per thread in which you can store some bits and which you dump when an error happens.
another option is to wrap a large section of code in a try: except: (for instance in a web application, one specific GUI page) and then use sys.exc_info() to print out the error and also the stack where it occurred
import sys
import traceback
try:
#some buggy code
x = ??
except:
print sys.exc_info()[0] #prints the exception class
print sys.exc_info()[1] #prints the error message
print repr(traceback.format_tb(sys.exc_info()[2])) #prints the stack