Suppose I want to introduce a try-except block while handling a txt file. Which of the two following way of capturing the possible exception is correct?
try:
h = open(filename)
except:
h.close()
print('Could not read file')
try:
h = open(filename)
except:
print('Could not read file')
In other words, should the h.close() be called even if the exception occurs or not?
Secondly, suppose that you have the following code
try:
h = open(filename)
"code line here1"
"code line here2"
except:
h.close()
print('Could not read file')
If an error occurs in "code line here1", should I use h.close() in the except block?
Is there a difference with the previous coding lines?
You should use with, it will close the file appropriately:
with open(filename) as h:
#
# do whatever you need...
#
# when you get here, the file will be closed automatically.
You can enclose that in a try/except block if needed. The file will always be properly closed:
try:
with open(filename) as h:
#
# do whatever you need...
#
except FileNotFoundError:
print('file not found')
Related
I have a script which wants to load integers from a text file. If the file does not exist I want the user to be able to browse for a different file (or the same file in a different location, I have UI implementation for that).
What I don't get is what the purpose of Exception handling, or catching exceptions is. From what I have read it seems to be something you can use to log errors, but if an input is needed catching the exception won't fix that. I am wondering if a while loop in the except block is the approach to use (or don't use the try/except for loading a file)?
with open(myfile, 'r') as f:
try:
with open(myfile, 'r') as f:
contents = f.read()
print("From text file : ", contents)
except FileNotFoundError as Ex:
print(Ex)
You need to use to while loop and use a variable to verify in the file is found or not, if not found, set in the input the name of the file and read again and so on:
filenotfound = True
file_path = myfile
while filenotfound:
try:
with open(file_path, 'r') as f:
contents = f.read()
print("From text file : ", contents)
filenotfound = False
except FileNotFoundError as Ex:
file_path = str(input())
filenotfound = True
recently i started learning Python and encountered a problem i can`t find an answer to.
Idea of the program is to ask for username, load a dictionary from JSON file, and if the name is in the dictionary - print the users favourite number.
The code, that loads the JSON file looks like this:
import json
fav_numbers = {}
filename = 'numbers.JSON'
name = input('Hi, what`s your name? ')
try:
with open(filename) as f_obj:
fav_numbers = json.load(f_obj)
except FileNotFoundError:
pass
if name in fav_numbers.keys():
print('Hi {}, your fav number is {}, right?'.format(name, fav_numbers[name]))
else:
number = input('Hi {}, what`s your favourte number? '.format(name))
fav_numbers[name] = number
with open(filename, 'w') as f_obj:
json.dump(fav_numbers, filename)
Still, as i try to run it, it crashes, telling me:
Exception has occurred: FileNotFoundError
[Errno 2] No such file or directory: 'numbers.JSON'
File "/home/niedzwiedx/Dokumenty/Python/ulubionejson.py", line 22, in <module>
with open(filename) as f_obj:
What i`m doing wrong to catch the exception? (Already tried changing the FileNotFoundError to OSError or IOError)
The error comes from you last line, outside of your try/except
with open(filename, 'w') as f_obj:
json.dump(fav_numbers, filename)
filename is a string, not a file.
You have to use
with open(filename, 'w') as f_obj:
json.dump(fav_numbers, f_obj)
For additional safety, you can surround this part with try/except too
try:
with open(filename, 'w') as f_obj:
json.dump(fav_numbers, f_obj)
except (FileNotFoundError, PremissionError):
print("Impossible to create JSON file to save data")
try:
masterpath = os.path.join(path, "master.txt")
with open(masterpath, 'r') as f:
s = f.read()
f.close()
exec(s)
with open(masterpath, 'w') as g:
g.truncate()
g.close()
os.remove(masterpath)
Here I want to read something in a .txt file and then erase content and delete it. But it always shows it cannot delete it as 'The process cannot access the file because it is being used by another process'.
Actually what I need is to delete the .txt file, but it cannot delete immediately sometimes, so I erase the content at first in case that it will be read again. So is there any good way to read something in a .txt file and then delete this file as soon and stable as possible?
You should NOT call f.close() nor g.close(). It is called automatically by with statement.
remove the unnecessary close() statements to start - like #grapes mentioned - why are you truncating what you are deleting? just delete it...
try:
masterpath = os.path.join(path, "master.txt")
with open(masterpath, 'r') as f:
s = f.read()
exec(s)
except Error as e:
print(e)
else:
os.remove(masterpath)
FYI, it is bad form to execute the contents of a file if you do not control the contents of said file.
another option:
masterpath = os.path.join(path, "master.txt")
with open(masterpath, 'r') as f:
try:
s = f.read()
except Error as e:
print(e)
else:
exec(s)
os.remove(masterpath)
Try to use short sleep in exception part:
try:
masterpath = os.path.join(path, "master.txt")
with open(masterpath, 'r') as f:
s = f.read()
f.close()
exec(s)
with open(masterpath, 'w') as g:
g.truncate()
g.close()
os.remove(masterpath)
except WindowsError:
time.sleep(sleep)
else:
break
Another way is to use:
os.remove(masterpath)
This question already has answers here:
Catching an exception while using a Python 'with' statement
(5 answers)
Closed 8 years ago.
A simple way to open a file and read its contents is using with:
with open ('file.txt', "r") as filehandle:
contents = filehandle.read()
But that does not include excepting file opening errors in a way that a try/except would:
try:
filehandle = open('file.txt', 'r')
contents = filehandle.read()
except IOError:
print('There was an error opening the file!')
sys.exit()
Is there a way to integrate a failure message in the with statement so that it exits gracefully if the opening fails that would be done in fewer lines of code than the second example yet provide the same functionality? If not that, is there anything more elegant (or minimalist) than the second form?
from contextlib import contextmanager
#contextmanager
def safe_open(fname,mode):
try:
fh = open(fname,mode)
except IOError:
print "ERROR OPENING FILE :",fname
sys.exit()
else:
yield fh
try:
fh.close()
except:
pass
with safe_open("nofile","rb") as f:
f.write("blah")
Im not sure that its more elegant but meh ...
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)