Why is else clause needed for try statement in python ?
Taking it forward:
try:
f = open('foo', 'r')
except IOError as e:
error_log.write('Unable to open foo : %s\n' % e)
else:
data = f.read()
f.close()
It occurs to me that the corner case solved by else clause still can be avoided by a nested try...except avoiding the need of else? :
try:
f = open('foo', 'r')
try:
data = f.read()
f.close()
except:
pass
except IOError as e:
error_log.write('Unable to open foo : %s\n' % e)
try..except..else may not be needed, but it can be nice. In this case, the try..except..else form is distinctly nicer, in my opinion.
Just because you can do without an element of syntax, doesn't make it useless. Decorator syntax is purely syntax sugar (the most obvious example, I think), for loops are just glorified while loops, et cetera. There's a good place for try..except..else and I would say this is one such place.
Besides, those two blocks of code are far from equivalent. If f.read() raises an exception (disk read error, data corruption inside the file or some other such problem), the first will raise an exception as it should but the second will lose it and think that everything has worked. For myself, I would prefer something more along these lines, which is shorter and still easier to understand:
try:
with open('foo', 'r') as f:
data = f.read()
except IOError as e:
error_log.write('Unable to open foo : %s\n' % e)
(This assumes that you want to catch errors in file.read and file.close. And I can't really see why you wouldn't.)
Actually, is not always needed you can simply do:
f = None
try:
f = open('foo', 'r')
except IOError:
error_log.write('Unable to open foo\n')
if f:
data = f.read()
f.close()
Related
For instance, I have a function like:
def example():
fp = open('example.txt','w+')
fp.write(str(1/0))
fp.close()
Then it will throw an exception because 1/0 is not defined. However, I can neither remove example.txt nor modify example.txt. But I have some important data in Python, so that I can't simply kill Python and run it again.
How could I finish opening the file when the function finish with an exception.
What shall we do if we didn't place a try:.. except:.. ?
with open('example.txt','w+') as fp:
try:
fp.write(...)
except ZeroDivisionError as e:
print('there was an error: {}'.format(e))
Using the with context manager any files opened by it will be closed automatically once they go out of scope.
You can wrap that in a try/except to handle the error and close the file reader before the program ends.
def example():
fp = open('example.txt', 'w+')
try:
fp.write(str(1/0))
except ZeroDivisionError:
fp.close()
fp.close()
Edit: The answer by #IanAuld is better than mine. It would be best to accept that one.
I use the code below to read in a text file (always a few thousand lines long). Is the except Exception as e block unnecessary?
try:
in_file=open(in_file,'rU')
try:
in_content=in_file.readlines()
except Exception as e:
sys.stderr.write('Error: %s\n' % e.message)
sys.exit(1)
finally:
in_file.close()
except IOError:
sys.stderr.write('I/O Error: Input file not found.')
sys.exit(1)
Also please tell me of the circumstances under which the file.readlines() method in Python will fail?
I believe that IOError is the only possible thing that can happen. This covers both the file not existing and inadequate permissions. Any python reference I have seen only has IOError with files :). I'm not sure by what you mean with the stack trace, since it seems to just print the error itself?
import sys
try:
with open("in_file",'rU') as in_file:
in_content=in_file.readlines()
except Exception as e: #Should be replaceable with IOError, doesn't hurt to not
sys.stderr.write('%s\n' % e)
sys.exit(1)
The pythonic way to read file looks like this:
with open(in_file_name,'rU') as in_file:
in_content = in_file.readlines()
This should give you all the benefits of your code. So you don't need to worry about what kind of errors can occur. Python will take care of it. A file opened using the with statement will be closed in case of an exception.
I have a directory that has bunch of sub directories, each subdir has many csv files, but I am only interest in certain csv file. So I wrote following python method, but I am unable to capture the file name, if I do *.csv it will find all the file but I don't want to all the files to be read in:
def gatherStats(template_file, csv_file):
for lang in getLanguageCodes(csv_file):
lang_dir = os.path.join(template_file, lang)
try:
for file in os.listdir(lang_dir):
if fnmatch.fnmatch(file, '*-*-template-users-data.csv'):
t_file = open(file, 'rb').read()
reader = csv.reader()
for row in reader:
print row
else:
print "didn't find the file"
except Exception, e:
logging.exception(e)
What am I doing wrong here? Is it a regular expression issue? Can we use regular expression with fnmath?
There are several problems with your code. Fix them first, then we might get to the bottom of what your issue really is.
First of all, don't use built-in names as variables, such as file. Rather replace it with filename.
Then os.path.join(lang_dir, filename) before opening the file. Meaning:
t_file = open(os.path.join(lang_dir, filename), 'rb').read()
How do you expect reader = csv.reader() to read your file if you don't reference your open file object in this line?
Your try/except block is a bit too wide for my taste. Take your time and narrow down the errors that actually can happen. Then decide which of them you want to ignore and which should crash your program. Take a close look at the exceptions actually thrown in this block. You'll probably find your issue there.
With the help provided by another user, I manage to fix the problem. I am putting this answer here for future reference for community.
def gatherStats(template_file, csv_file):
for lang in getLanguageCodes(csv_file):
lang_dir = os.path.join(template_file, lang)
try:
for filename in os.listdir(lang_dir):
path = os.path.join(lang_dir, filename)
if re.search(r'-.+-template-users-data.csv$',filename):
with open(path, 'rb') as template_user_data_file:
reader = csv.reader(template_user_data_file)
try:
for row in reader:
print row
except csv.ERROR as e:
logging.error(e)
else:
print "didn't find the file"
except Exception, e:
logging.exception(e)
In a try...except block i want to log the Exception error message to a file in the except path.
try:
doc = etree.parse(urllib2.urlopen(url))
except Exception, e:
print '%s: %s' % (e, url)
with open('error.txt', 'a') as f:
f.write('%s:%s\n' % url, e)
return
The print shows the error, but the with open ... f.write is not excecuted.
in the same script the relaxng validation is written to file
if not RELAXNG.validate(doc):
with open('error.txt', 'a') as f:
f.write('%s\n' % RELAXNG.error_log)
return
Can somebody explain to me, why
with open('myfile.txt', 'a') as f
f.write( ...
is posible in the if statement, but not in an except?
write() does not accept multiple arguments; you are probably missing parenthesis:
f.write('%s:%s\n' % (url, e))
Other than that, use absolute paths, not relative, as you can easily write the file in an unexpected place otherwise.
File operations inside except works fine.
>>> try:
raise SyntaxError("Hello")
except Exception:
with open("in.txt") as f:
print "F"
F
It should work. Try this for example:
try:
raise Exception
except Exception:
with open('error.txt', 'a') as f:
f.write('foobar')
If you run the above you will see foobar been written to file.
Is error.txt writeable by your process? There is some reason it's not writing to your file but it's not because the 'with' file context isn't allowed inside an except block.
I am going to start of by showing the code I have thus far:
def err(em):
print(em)
exit
def rF(f):
s = ""
try:
fh = open(f, 'r')
except IOError:
e = "Could not open the file: " + f
err(e)
try:
with fh as ff:
next(ff)
for l in ff:
if ">" in l:
next(ff)
else:
s += l.replace('\n','').replace('\t','').replace('\r','')
except:
e = "Unknown Exception"
err(e)
fh.close()
return s
For some reason the python shell (I am using 3.2.2) freezes up whenever I tried to read a file by typing:
rF("mycobacterium_bovis.fasta")
The conditionals in the rF function are to prevent reading each line that starts with a ">" token. These lines aren't DNA/RNA code (which is what I am trying to read from these files) and should be ignored.
I hope anyone can help me out with this, I don't see my error.
As per the usual, MANY thanks in advance!
EDIT:
*The problem persists!*
This is the code I now use, I removed the error handling which was a fancy addition anyway, still the shell freezes whenever attempting to read a file. This is my code now:
def rF(f):
s = ""
try:
fh = open(f, 'r')
except IOError:
print("Err")
try:
with fh as ff:
next(ff)
for l in ff:
if ">" in l:
next(ff)
else:
s += l.replace('\n','').replace('\t','').replace('\r','')
except:
print("Err")
fh.close()
return s
You didn't ever define e.
So you'll get a NameError that is being hidden by the naked except:.
This is why it is good and healthy to specify the exception, e.g.:
try:
print(e)
except NameError as e:
print(e)
In cases like yours, though, when you don't necessarily know what the exception will be you should at least use this method of displaying information about the error:
import sys
try:
print(e)
except: # catch *all* exceptions
e = sys.exc_info()[1]
print(e)
Which, using the original code you posted, would have printed the following:
name 'e' is not defined
Edit based on updated information:
Concatenating a string like that is going to be quite slow if you have a large file.
Consider instead writing the filtered information to another file, e.g.:
def rF(f):
with open(f,'r') as fin, open('outfile','w') as fou:
next(fin)
for l in fin:
if ">" in l:
next(fin)
else:
fou.write(l.replace('\n','').replace('\t','').replace('\r',''))
I have tested that the above code works on a FASTA file based on the format specification listed here: http://en.wikipedia.org/wiki/FASTA_format using Python 3.2.2 [GCC 4.6.1] on linux2.
A couple of recommendations:
Start small. Get a simple piece working then add a step.
Add print() statements at trouble spots.
Also, consider including more information about the contents of the file you're attempting to parse. That may make it easier for us to help.