I am running the following code very often to write to files from Python using the following:
def function():
file = os.path.join(os.path.dirname(os.path.abspath(__file__)), '../../my_file')
fifo = open(file, 'w')
if (os.path.isfile(file) and os.access(file, os.W_OK)):
fifo.write("stuff")
fifo.close()
else:
time.sleep(1)
function()
Unfortunately, I get the following error (not all the time):
IOError: [Errno 2] No such file or directory
This is self-explanatory, but I do not understand then why all the precautions do not work, like isfile or access..W_OK ? How do I avoid having this issue?
Also, the slower the machine, the less often the error is encountered.
See also "LBYL vs EAFP in Java?":
Instead of checking if the action is ok (LBYL), you should do an EAFP approach. Just do what you want to do and check if it has worked correctly.
Besides, better don't call function() recursively, it might lead to a stack overflow if the error persists.
Better do
def function():
file = os.path.join(os.path.dirname(os.path.abspath(__file__)), '../../my_file')
while True:
try:
with open(file, 'w') as file: # automatically closes...
file.write("some stuff")
except IOError, e:
time.sleep(1)
continue
break # the while loop
Related
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!")
I'm attempting to write error handling in Python 2.7 for when an IOError exception is raised after a user enters a filename.
I have tried a couple of solutions our there on the internet including:
How to retry after exception?
Get a Try statement to loop around until correct value obtained
This is my original code:
while True:
try:
with open (userFile, 'r') as txtFile:
for curLine in txtFile:
curLine = curLine.rstrip("\n\r")
idList.append(curLine)
except IOError:
print("File does not exist")
Whenever the IOError exception is raised it goes into an infinite loop, printing "File does not exist" over and over again. In the instance where I limit the attempts by adding a range, it goes through that range, printing over and over again and then exits the script. Does anyone have an idea why this keeps looping when the exception is raised?
This will be much easier if you split the separate concerns into functions, i.e. (i) warning the user if a file doesn't exist and (ii) reading the contents of the file into a list of lines:
def read_file(f):
# you can't read a file line-by-line and get line endings that match '\n\r'
# the following will match what your code is trying to do, but perhaps not
# what you want to accomplish..?
return f.read().split("\n\r") # are you sure you haven't switched these..?
def checked_read_file(fname):
try:
with open(fname, 'rb') as fp: # you'll probably need binary mode to read \r
return read_file(fp)
except IOError:
print("File does not exist")
return False
then you can write your while loop:
while True:
result = checked_read_file(user_file)
if result is not False: # this is correct since the empty list is false-y
break
user_file = input("Enter another filename: ") # or user_file = raw_input("...: ") if you're on Python 2
# here result is an array of lines from the file
I need to prevent a python script from running more than once. So far I have:
import fcntl
def lockFile(lockfile):
fp = open(lockfile, 'w')
try:
fcntl.flock(fp, fcntl.LOCK_EX | fcntl.LOCK_NB)
except IOError:
return False
return True
if not lockFile("myfile.lock"):
sys.exit(0)
Problem is the sys.exit() never gets called even if the file is there. Maybe this is a platform dependent way of doing things? I just need to write a lockfile, check for its existence and if it's not there or stale, create a new one. Ideas?
Writing a file will create a new file if none exist; you could instead try to read the file first: if there is none, an error is raised and a file a file written; if there is a file, the program exits.
try:
with open('lockfile.txt', 'r') as f:
lock = f.readline().strip().split()
if lock[0] == 'locked':
print('exiting')
sys.exit(0)
except FileNotFoundError:
with open('lockfile.txt', 'w') as f:
f.write('locked')
print('file written')
if __name__ == '__main__':
pass
If you need something more sophisticated, you could look up the atexit module
You can check if you file exists by using os.path.exists (docs here). If it does, then you can use the sys.exit you mentioned before. If you need something more than sys.exit, try the atexit module #Reblochon suggested. The script will then assume the file is ready to lock and the method will report its success back to the user via a boolean.
import os
import sys
import fcntl
FILE_NAME = 'myfile.lock'
def lockFile(lockfile):
fp = open(lockfile, 'w') # create a new one
try:
fcntl.flock(fp, fcntl.LOCK_EX | fcntl.LOCK_NB)
success = True # the file has been locked
except IOError:
success = False # an error occurred
fp.close() # make sure to close your file
return success
if os.path.exists(FILE_NAME): # exit the script if it exists
sys.exit(0)
print('success', lockFile(FILE_NAME))
I'm processing a file and then want to remove it. My code ends with:
...
tar.extractall(dir=...)
tar.close()
os.remove(filename)
This sometimes causes an error:
[Errno 16] Resource busy: 'skyimage/sgptsiskyimageC1.a1.20160415.000000.jpg.tar'
I was able to work around this by telling Python to keep trying until it works:
while True:
try:
os.remove(filename)
break
except OSError as err:
continue
Is there a more Pythonic way to do this?
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.”)