Exception handling in python file i/O - python

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.

Related

Python [Errno 13] - Exception handling when saving a file that is opened by user

I'm using Pandas and Xlsxwriter to analyze some data, and then periodically create a Excel simple report for another users. The report should always get overwritten by the last one I export. Also, once I export it, it gets automatically opened to review it quickly.
The only issue I have is that I get an [Errno 13] if someone has left that file opened (or even if I'm using it, which I must admit happens).
IOError: [Errno 13] Permission denied: '2320PLFY2018.xlsx'
So i just wanted to add some Error handling to that IOError at the end of the XLSXWRITER part, to let me know about it, and give me a chance to close the file. Started with a simple attempt just to give me an error message. Tried several times but cant make it work. This is one attempt:
try:
writer.save()
os.startfile(company_code_choice + 'PLFY2018.xlsx')
except IOError as e:
print(e.errno)
Also tried without specifying the Error type:
while True:
try:
writer.save()
os.startfile(company_code_choice + 'PLFY2018.xlsx')
break
except:
print "Close the file!"
I'm new to creating code so I apologize if this is an obvious question...
I've been googling for this all morning and read several other questions but couldn't make it work on my code. Thanks in advance-
The best thing that I can think of that may cause this error is that one of the functions that you call inside your try statement is handling the exception inside itself so that your exception handling becomes ineffective.
To make sure:
Try to throw an exception manually from your try block so that you make sure the exception handling works in general.
If the aforementioned assumption is true you can figure out which function is handling the exception inside itself by manually raising an exception once before and once after the call.
To demonstrate what I mean:
while True:
sleep(1)
try:
raise Exception("my exception")
writer.save()
os.startfile(company_code_choice + 'PLFY2018.xlsx')
break
except Exception as e:
print ("Close the file: ", e)
You should definitely capture your raised exception otherwise, something is wrong with your code. Try to simply or check what prevents the excepted behavior if happened. If you could capture your raised exception then the next time:
while True:
sleep(1)
try:
writer.save()
raise Exception("my exception")
os.startfile(company_code_choice + 'PLFY2018.xlsx')
break
except Exception as e:
print ("Close the file: ", e)
So that you either capture your raised exception which means writer.save() does not handle the exception inside itself or you get the same error which means writer.save() handles the exception. By continuing this procedure all over the try block of your code you must be able to figure out which function is making trouble.
That's the best thing I can think of now. I hope it helps. But if I'm right then you could only figure out the source of the error but I don't know how you can achieve the behavior you would like. So maybe you can find a clue on the documentation.

How to know and raise exact exception in Django views

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)

try-except-raise clause, good behaviour?

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.

Why do we need the "finally" clause in Python?

I am not sure why we need finally in try...except...finally statements. In my opinion, this code block
try:
run_code1()
except TypeError:
run_code2()
other_code()
is the same with this one using finally:
try:
run_code1()
except TypeError:
run_code2()
finally:
other_code()
Am I missing something?
It makes a difference if you return early:
try:
run_code1()
except TypeError:
run_code2()
return None # The finally block is run before the method returns
finally:
other_code()
Compare to this:
try:
run_code1()
except TypeError:
run_code2()
return None
other_code() # This doesn't get run if there's an exception.
Other situations that can cause differences:
If an exception is thrown inside the except block.
If an exception is thrown in run_code1() but it's not a TypeError.
Other control flow statements such as continue and break statements.
You can use finally to make sure files or resources are closed or released regardless of whether an exception occurs, even if you don't catch the exception. (Or if you don't catch that specific exception.)
myfile = open("test.txt", "w")
try:
myfile.write("the Answer is: ")
myfile.write(42) # raises TypeError, which will be propagated to caller
finally:
myfile.close() # will be executed before TypeError is propagated
In this example you'd be better off using the with statement, but this kind of structure can be used for other kinds of resources.
A few years later, I wrote a blog post about an abuse of finally that readers may find amusing.
They are not equivalent. finally code is run no matter what else happens*.
It is useful for cleanup code that has to run.
*:
As Mark Byers commented, anything causes the process to terminate immediately also prevents the finally-code to run.
The latter could be an os._exit(). or powercut, but an infinite loop or other things also fall into that category.
To add to the other answers above, the finally clause executes no matter what whereas the else clause executes only if an exception was not raised.
For example, writing to a file with no exceptions will output the following:
file = open('test.txt', 'w')
try:
file.write("Testing.")
print("Writing to file.")
except IOError:
print("Could not write to file.")
else:
print("Write successful.")
finally:
file.close()
print("File closed.")
OUTPUT:
Writing to file.
Write successful.
File closed.
If there is an exception, the code will output the following, (note that a deliberate error is caused by keeping the file read-only.
file = open('test.txt', 'r')
try:
file.write("Testing.")
print("Writing to file.")
except IOError:
print("Could not write to file.")
else:
print("Write successful.")
finally:
file.close()
print("File closed.")
OUTPUT:
Could not write to file.
File closed.
We can see that the finally clause executes regardless of an exception. Hope this helps.
Here's a peice of code to clarify the difference:
...
try:
a/b
print('In try block')
except TypeError:
print('In except block')
finally:
print('In finally block')
print('Outside')
a, b = 0, 1
Output:
In try block
In finally block
Outside
(No errors, except block skipped.)
a, b = 1, 0
Output:
In finally block
Traceback (most recent call last):
a/b
ZeroDivisionError: division by zero
(No exception handling is specified for ZeroDivisionError and only the finally block is executed.)
a, b = 0, '1'
Output:
In except block
In finally block
Outside
(Exception is handled properly and the program is not interrupted.)
Note: If you have an except block to handle all types of errors, the finally block will be superfluous.
As explained in the documentation, the finally clause is intended to define clean-up actions that must be executed under all circumstances.
If finally is present, it specifies a ‘cleanup’ handler. The try
clause is executed, including any except and else clauses. If an
exception occurs in any of the clauses and is not handled, the
exception is temporarily saved. The finally clause is executed. If
there is a saved exception it is re-raised at the end of the finally
clause.
An example:
>>> def divide(x, y):
... try:
... result = x / y
... except ZeroDivisionError:
... print("division by zero!")
... else:
... print("result is", result)
... finally:
... print("executing finally clause")
...
>>> divide(2, 1)
result is 2.0
executing finally clause
>>> divide(2, 0)
division by zero!
executing finally clause
>>> divide("2", "1")
executing finally clause
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 3, in divide
TypeError: unsupported operand type(s) for /: 'str' and 'str'
As you can see, the finally clause is executed in any event. The TypeError raised by dividing two strings is not handled by the except clause and therefore re-raised after the finally clause has been executed.
In real world applications, the finally clause is useful for releasing external resources (such as files or network connections), regardless of whether the use of the resource was successful.
The code blocks are not equivalent. The finally clause will also be run if run_code1() throws an exception other than TypeError, or if run_code2() throws an exception, while other_code() in the first version wouldn't be run in these cases.
In your first example, what happens if run_code1() raises an exception that is not TypeError? ... other_code() will not be executed.
Compare that with the finally: version: other_code() is guaranteed to be executed regardless of any exception being raised.
Using delphi professionally for some years taught me to safeguard my cleanup routines using finally. Delphi pretty much enforces the use of finally to clean up any resources created before the try block, lest you cause a memory leak. This is also how Java, Python and Ruby works.
resource = create_resource
try:
use resource
finally:
resource.cleanup
and resource will be cleaned up regardless of what you do between try and finally. Also, it won't be cleaned up if execution never reaches the try block. (i.e. create_resource itself throws an exception) It makes your code "exception safe".
As to why you actually need a finally block, not all languages do. In C++ where you have automatically called destructors which enforce cleanup when an exception unrolls the stack. I think this is a step up in the direction of cleaner code compared to try...finally languages.
{
type object1;
smart_pointer<type> object1(new type());
} // destructors are automagically called here in LIFO order so no finally required.
Finally can also be used when you want to run "optional" code before running the code for your main work and that optional code may fail for various reasons.
In the following example, we don't know precisely what kind of exceptions store_some_debug_info might throw.
We could run:
try:
store_some_debug_info()
except Exception:
pass
do_something_really_important()
But, most linters will complain about catching too vague of an exception. Also, since we're choosing to just pass for errors, the except block doesn't really add value.
try:
store_some_debug_info()
finally:
do_something_really_important()
The above code has the same effect as the 1st block of code but is more concise.
finally is for defining "clean up actions". The finally clause is executed in any event before leaving the try statement, whether an exception (even if you do not handle it) has occurred or not.
I second #Byers's example.
Perfect example is as below:
try:
#x = Hello + 20
x = 10 + 20
except:
print 'I am in except block'
x = 20 + 30
else:
print 'I am in else block'
x += 1
finally:
print 'Finally x = %s' %(x)
A try block has just one mandatory clause: The try statement.
The except, else and finally clauses are optional and based on user preference.
finally:
Before Python leaves the try statement, it will run the code in the finally block under any conditions, even if it's ending the program. E.g., if Python ran into an error while running code in the except or else block, the finally block will still be executed before stopping the program.
Try running this code first without a finally block,
1 / 0 causes a divide by zero error.
try:
1 / 0
print(1)
except Exception as e:
1 / 0
print(e)
Then try running this code,
try:
1 / 0
print(1)
except Exception as e:
1 / 0
print(e)
finally:
print('finally')
For the first case you don't have a finally block,
So when an error occurs in the except block the program execution halts and you cannot execute anything after the except block.
But for the second case,
The error occurs but before the program halts python executes the finally block first and then causes the program to halt.
Thats is why you use finally and do stuff that is really important.
Run these Python3 codes to watch the need of finally:
CASE1:
count = 0
while True:
count += 1
if count > 3:
break
else:
try:
x = int(input("Enter your lock number here: "))
if x == 586:
print("Your lock has unlocked :)")
break
else:
print("Try again!!")
continue
except:
print("Invalid entry!!")
finally:
print("Your Attempts: {}".format(count))
CASE2:
count = 0
while True:
count += 1
if count > 3:
break
else:
try:
x = int(input("Enter your lock number here: "))
if x == 586:
print("Your lock has unlocked :)")
break
else:
print("Try again!!")
continue
except:
print("Invalid entry!!")
print("Your Attempts: {}".format(count))
Try the following inputs each time:
random integers
correct code which is 586(Try this and you will get your answer)
random strings
** At a very early stage of learning Python.
I was trying to run a code where i wanted to read excel sheets. Issue was, if there is a file which has no sheet named say : SheetSum I am not able to move it to error location!! Code i wrote was:
def read_file(data_file):
# data_file = '\rr\ex.xlsx'
sheets = {}
try:
print("Reading file: "+data_file)
sheets['df_1'] = pd.read_excel(open(data_file,'rb'), 'SheetSum')
except Exception as excpt:
print("Exception occurred", exc_info=True)
return sheets
read_file(file)
shutil.move( file, dirpath +'\\processed_files')
Giving Error :
[WinError 32] The process cannot access the file because it is being
used by another process
I had to add full try except with finally block and tell finally i need to close the file in any case like:
def read_file(data_file):
# data_file = '\rr\ex.xlsx'
sheets = {}
sheets_file = None
try:
print("Reading file: "+data_file)
sheets_file = open(data_file,'rb')
sheets['df_1'] = pd.read_excel(sheets_file, 'SheetSum')
except Exception as excpt:
print("Exception occurred", exc_info=True)
finally:
if sheets_file:
sheets_file.close()
return sheets
read_file(file)
shutil.move( file, dirpath +'\\processed_files')
Otherwise, file still remains open is the background.
If finally is present, it specifies a cleanup handler. The try
clause is executed, including any except and else clauses. If an
exception occurs in any of the clauses and is not handled, the
exception is temporarily saved. The finally clause is executed. If
there is a saved exception it is re-raised at the end of the finally
clause. If the finally clause raises another exception, the saved
exception is set as the context of the new exception.
..More Here
Just to enable Abhijit Sahu's comment on this answer to be seen much better and with syntax highlighting:
Like this, you can observe what happens with which code block when:
try:
x = Hello + 20
x = 10 + 20
except:
print 'I am in except block'
x = 20 + 30
else:
print 'I am in else block'
x += 1
finally:
print 'Finally x = %s' %(x)
Here you can see how try, except, else, and finally work together. Actually, since your code doesn't have 'else' then what you claimed is right. I.e., There is no difference between the two statements that you wrote. But if 'else' is used somewhere, then 'finally' makes a difference

Nesting "for" loop within a "try" operator

Folks,
I've resigned myself to working around this problem, but I wanted to check if Python is really acting as expected.
In the example, "sample.txt" is any multi-line text file that is read and parsed.
try:
file=open('sample.txt','r')
for line in file:
(some action here)
except:
print "Couldn't open file"
file.close()
The actions I observe are that "sample.txt" is opened and the first line handled, the logic then falls through to the "except" clause.
WAD or is this a bug?
If the code in the except block runs it is because an exception was raised. You swallow the exception which makes it hard to know what's going wrong.
Your error message suggests that you are attempting to trap errors raised in the file open. But since your try block surrounds the entire processing of the file, exceptions raised in the processing, as opposed to the file open, will be mis-reported as "Could not open file". If you really must handle the exception then you need to move the for loop to be after the except block.
Personally I'd be inclined to simply ignore the exception and let the default handling of the exception halt execution:
with open('sample.txt','r') as file:
for line in file:
(some action here)
If you must handle the exception then be discerning about the class exception that you handle. For example, handle just IOError since that is what open raises in case of failure.
try:
with open('sample.txt','r') as file:
for line in file:
(some action here)
except IOError:
except IOError as (errno, strerror):
print "I/O error({0}): {1}".format(errno, strerror)
It's not failing on the open line, then. What's the exception?
try:
file=open('sample.txt','r')
for line in file:
(some action here)
except:
print "Exception:"
import traceback; traceback.print_exc()
file.close()
That bare except catches all exceptions, including ones in the (some action here) part. Restructure that as:
try:
inputfile = open('sample.txt', 'r')
except:
print "Couldn't open file"
else:
for line in inputfile: pass
inputfile.close()
Or even better:
with open('sample.txt', 'r') as inputfile:
for line in inputfile: pass
In general, only wrap the bare minimum amount of code possible inside a try block so that you're not accidentally handling exceptions you're not really prepared to deal with.
your code risks raising another assertion trying to close file if for some reason the open() call fails. This is because the file variable won't be set if open() raises an exception, and so your call further down will reference a variable that doesn't exist.
If possible, try using the with statement:
with open('sample.txt', 'r') as file:
try:
for line in file:
(some action)
except:
print "Exception"
import traceback; traceback.print_exc()
This will make sure that file is closed afterwards regardless of what happens inside the with statement.
Try using readlines to generate a list of all lines in the file. And you also shouldnt be catching general errors without at least printing the error code.
try:
file=open('sample.txt','r')
for line in file.readlines():
(some action here)
except Exception, e:
print str(e)
file.close()
The actions I observe are that "sample.txt" is opened and the first line handled, the logic then falls through to the "except" clause.
Yes, this is the case. But this only occurs as long as the file exists.
As for the error falling through to the except clause (assuming the file exists), that implies that there is an issue with the parsing logic you've implemented. We can't be sure what it is since the except catches everything, and unless it's re-raised (may as well not catch it then...), or you print the stack trace from the exception object, you can't tell what is going wrong or where. In general, this is why catching everything is frowned upon; it makes debugging unnecessarily difficult.
I also noticed that you are closing the file at the very end. This is probably another source of errors, since the file only exists within the scope of try. You have two options:
Include file.close() inside of your try block so the file is properly closed after you're done, or
Use the with statement as a context manager to automatically close the file when you're done. #David Heffernan's example is one that's similar to one I would write.

Categories

Resources