I am trying to open file "data.txt" in the cwd and readthe lines,is there a oneliner(or close ) to exit the subroutine if the file doesnt exist..i know there are ways like using os.path.exists and try/except IO error but am interested in one-liner or the smartest way
def readfile ():
f = open('data.txt')
lines = f.readlines()
f.close()
you can use with open
with open('data.txt') as f:
lines = f.readlines()
The with statement will automatically close the file after the nested block of code. The advantage of using a with statement is that it is guaranteed to close the file no matter how the nested block exits. If an exception occurs before the end of the block, it will close the file before the exception is caught by an outer exception handler.
If the nested block were to contain a return statement, or a continue or break statement, the with statement would automatically close the file in those cases, too.
You can use os.path.exists and a conditional expression:
import os.path as opath
def readlines(path):
return open(path).readlines() if opath.exists(path) else []
And if you're into lazy evaluation (it will only read as many lines as the caller consumes), combine it with a generator expression:
import os.path as opath
def readlines(path):
try:
return (l for l in open(path)) if opath.exists(path) else ()
except FileNotFoundError:
return ()
Related
I have a simple python code to open the .csv file and check for exceptions.
The file exists in my current folder and it has more than 2 lines of data.
But the for loop in the else part is not executing.. because I'm getting zero lines to count.
# Base class for defining your own user-defined exceptions.
class Error(Exception):
'''Base class for other exceptions'''
pass
# own exception class as a subclass of error
class EmptyFileError(Error):
pass
# raise error
try:
# open the file (no error check for this example).
thefile = open('people.csv')
# count the number of lines in file.
file_content = thefile.readlines()
line_count = len(file_content)
# If there is fewer than 2 lines, raise exception.
if line_count < 2:
raise EmptyFileError
# Handles missing file error.
except FileNotFoundError:
print('\n There is no people.csv file here')
# Handles my custom error for too few rows.
except EmptyFileError:
print('\nYour people.csv does not have enough stuff')
# Handles all other Exceptions
except Exceptions as e:
# Show the error
print('\n\nFailed: The error was '+str(e))
# Close the file
thefile.close()
else:
print(thefile.name)
# file must be open if we got here
for one_line in file_content:
print(list(one_line.split(',')))
thefile.close()
print('Success')
I was able to see the output of the file name and success message from the else part but not the for loop part. There were no exceptions occurred and so the file was never closed before else part.
What could be the problem?
Solved with the help of #Ralf answer.
You already consumed all the lines of the file by calling thefile.readlines(); when you start the loop for one_line in thefile: there are no more lines to read, so the loop never gets executed.
Possible solution: use a variable to hold the file contents.
line_list = thefile.readlines()
line_count = len(line_list)
and the iterate over that:
for one_line in line_list:
Here are some related questions with more info:
Read multiple times lines of the same file Python
Why can't I call read() twice on an open file?
I have two potential file-paths where my application can read specific data from. If one fails, I want it to read from the other.
My intuitive attempt to do so was with try...except clauses, having something as below:
# Try the first file path
try:
file = open(possible_path_1)
content = file.read()
# File is not in first location, try the second
except IOError:
file = open(possible_path_2)
content = file.read()
# Could not read from either location, throw custom CriticalException
except IOError:
raise CriticalException("Could not read the file!")
However, this does not seem to work as intuitively expected. The second IOError is never caught. Why is this the case? Is there any "clean" way to read from one file path or the other without having to manually check os.path.exists(filepath) and os.path.isfile(filepath)?
Here's an alternative, but not sure if it is "prettier":
for path in paths:
try:
file = open(path)
content = file.read()
# File is not in first location, try the second
except IOError:
continue
break
else: # for-else gets executed if break never happens
raise CriticalException("Could not read the file!")
Assuming you have all your possible paths in some container, paths
Although honestly, I simply wouldn't use exception handling here, I think this is much clearer (and of course, I would use pathlib not os.path:
from pathlib import Path
for path in map(Path, paths):
if path.exists():
content = path.read_text()
break
else:
raise CriticalException("Could not read the file!")
In my code, user uploads file which is saved on server and read using the server path. I'm trying to delete the file from that path after I'm done reading it. But it gives me following error instead:
An error occurred while reading file. [WinError 32] The process cannot access the file because it is being used by another process
I'm reading file using with, and I've tried f.close() and also f.closed but its the same error every time.
This is my code:
f = open(filePath)
with f:
line = f.readline().strip()
tempLst = line.split(fileSeparator)
if(len(lstHeader) != len(tempLst)):
headerErrorMsg = "invalid headers"
hjsonObj["Line No."] = 1
hjsonObj["Error Detail"] = headerErrorMsg
data['lstErrorData'].append(hjsonObj)
data["status"] = True
f.closed
return data
f.closed
after this code I call the remove function:
os.remove(filePath)
Edit: using with open(filePath) as f: and then trying to remove the file gives the same error.
Instead of:
f.closed
You need to say:
f.close()
closed is just a boolean property on the file object to indicate if the file is actually closed.
close() is method on the file object that actually closes the file.
Side note: attempting a file delete after closing a file handle is not 100% reliable. The file might still be getting scanned by the virus scanner or indexer. Or some other system hook is holding on to the file reference, etc... If the delete fails, wait a second and try again.
Use below code:
import os
os.startfile('your_file.py')
To delete after completion:
os.remove('your_file.py')
This
import os
path = 'path/to/file'
with open(path) as f:
for l in f:
print l,
os.remove(path)
should work, with statement will automatically close the file after the nested block of code
if it fails, File could be in use by some external factor. you can use Redo pattern.
while True:
try:
os.remove(path)
break
except:
time.sleep(1)
There is probably an application that is opening the file; check and close the application before executing your code:
os.remove(file_path)
Delete files that are not used by another application.
I have a txt file called test.txt with 4 lines in it. I want to copy lines containing the word 'exception' into a new file from command line argument. I have managed this far. But I also want to exception handle this for IO error. That is if from the command line, somebody misspells the word test.txt, it will throw an exception. This is my current code. Please help! I'm a beginner. Presently, if I misspell it intentionally, it is not showing the error message I intend it to show.
import sys
def Cat(filename):
try:
f = open(filename, 'rU')
for line in f:
print (line),
return 3
except IOError:
print('\nIO error!!', filename)
def main():
f1 = open(sys.argv[1])
f2 = open(sys.argv[2], 'w')
for line in f1:
if 'exception' in line:
f2.write(line)
if __name__ == '__main__':
main()
First check if source file exists and readable -
if not (os.path.exists(file1) and os.access(file1, os.R_OK)):
print "file1 does not exists or not readable"
sys.exit(1)
else:
//good to go
and then handle writing of destination file with try except block.
You need to put the open() inside a try-except block, just as you did in Cat().
Currently, you are not calling Cat(), and the open() in main() is not inside a try-except block.
Since you said you are a beginner in Python I'll assume this a sort of "learning code". So, I won't tell you anything about the design. Also, you should do what #NPE says too.
You can try this in your main function in order to reach your goal:
def main():
filename = open(sys.argv[1])
if filename != "test.txt":
raise Exception("Here goes the message error you want to show")
f2 = open(sys.argv[2], 'w')
for line in f1:
if 'exception' in line:
f2.write(line)
You forgot to call Cat()
before
f2 = open(sys.argv[2], 'w')
Cat(f1)
for line in f1:
and in the Cat function you will need to raise exception to stop the execution
print('\nIO error!!', filename)
raise IOError('Invalid filename')
I'm trying to read all files from a folder that matches a certain criteria. My program crashes once I have an exception raised. I am trying to continue even if there's an exception but it still stops executing.
This is what I get after a couple of seconds.
error <type 'exceptions.IOError'>
Here's my code
import os
path = 'Y:\\Files\\'
listing = os.listdir(path)
try:
for infile in listing:
if infile.startswith("ABC"):
fo = open(infile,"r")
for line in fo:
if line.startswith("REVIEW"):
print infile
fo.close()
except:
print "error "+str(IOError)
pass
Put your try/except structure more in-wards. Otherwise when you get an error, it will break all the loops.
Perhaps after the first for-loop, add the try/except. Then if an error is raised, it will continue with the next file.
for infile in listing:
try:
if infile.startswith("ABC"):
fo = open(infile,"r")
for line in fo:
if line.startswith("REVIEW"):
print infile
fo.close()
except:
pass
This is a perfect example of why you should use a with statement here to open files. When you open the file using open(), but an error is catched, the file will remain open forever. Now is better than never.
for infile in listing:
try:
if infile.startswith("ABC"):
with open(infile,"r") as fo
for line in fo:
if line.startswith("REVIEW"):
print infile
except:
pass
Now if an error is caught, the file will be closed, as that is what the with statement does.
Move the try/except inside the for loop.
Like in:
import os
path = 'C:\\'
listing = os.listdir(path)
for infile in listing:
try:
if infile.startswith("ABC"):
fo = open(infile,"r")
for line in fo:
if line.startswith("REVIEW"):
print infile
fo.close()
except:
print "error "+str(IOError)
You're code is doing exactly what you're telling it to do. When you get an exception, it jumps down to this section:
except:
print "error "+str(IOError)
pass
Since there's nothing after that, the program ends.
Also, that pass is superfluous.
As per strictest interpretation of the question "continue even if there's an exception". Python gives us a keyword "finally" which executes a block of code no matter what precedes it. The only issue with this method will run a block of code regardless of the type of error, which might not be desirable for all cases.
try:
unreal = 3/0 # raises divide by zero exception
print(unreal)
# handles zerodivision exception
except :
print("Can't divide by zero, 0 has no multiplicative inverse")
finally:
# this block is always executed
print("Brahmagupta claimed that “zero divided by a zero is zero.”)