I'm trying to control exceptions when reading files, but I have a problem. I'm new to Python, and I am not yet able to control how I can catch an exception and still continue reading text from the files I am accessing. This is my code:
import errno
import sys
class Read:
#FIXME do immutables this 2 const
ROUTE = "d:\Profiles\user\Desktop\\"
EXT = ".txt"
def setFileReaded(self, fileToRead):
content = ""
try:
infile = open(self.ROUTE+fileToRead+self.EXT)
except FileNotFoundError as error:
if error.errno == errno.ENOENT:
print ("File not found, please check the name and try again")
else:
raise
sys.exit()
with infile:
content = infile.read()
infile.close()
return content
And from another class I tell it:
read = Read()
print(read.setFileReaded("verbs"))
print(read.setFileReaded("object"))
print(read.setFileReaded("sites"))
print(read.setFileReaded("texts"))
Buy only print this one:
turn on
connect
plug
File not found, please check the name and try again
And no continue with the next files. How can the program still reading all files?
It's a little difficult to understand exactly what you're asking here, but I'll try and provide some pointers.
sys.exit() will terminate the Python script gracefully. In your code, this is called when the FileNotFoundError exception is caught. Nothing further will be ran after this, because your script will terminate. So none of the other files will be read.
Another thing to point out is that you close the file after reading it, which is not needed when you open it like this:
with open('myfile.txt') as f:
content = f.read()
The file will be closed automatically after the with block.
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.
My goal is to know if a file is locked by another process or not, even if I don't have access to that file!
So to be more clear, let's say I'm opening the file using python's built-in open() with 'wb' switch (for writing). open() will throw IOError with errno 13 (EACCES) if:
the user does not have permission to the file or
the file is locked by another process
How can I detect case (2) here?
(My target platform is Windows)
You can use os.access for checking your access permission. If access permissions are good, then it has to be the second case.
As suggested in earlier comments, os.access does not return the correct result.
But I found another code online that does work. The trick is that it attempts to rename the file.
From: https://blogs.blumetech.com/blumetechs-tech-blog/2011/05/python-file-locking-in-windows.html
def isFileLocked(filePath):
'''
Checks to see if a file is locked. Performs three checks
1. Checks if the file even exists
2. Attempts to open the file for reading. This will determine if the file has a write lock.
Write locks occur when the file is being edited or copied to, e.g. a file copy destination
3. Attempts to rename the file. If this fails the file is open by some other process for reading. The
file can be read, but not written to or deleted.
#param filePath:
'''
if not (os.path.exists(filePath)):
return False
try:
f = open(filePath, 'r')
f.close()
except IOError:
return True
lockFile = filePath + ".lckchk"
if (os.path.exists(lockFile)):
os.remove(lockFile)
try:
os.rename(filePath, lockFile)
sleep(1)
os.rename(lockFile, filePath)
return False
except WindowsError:
return True
According to the docs:
errno.EACCES
Permission denied
errno.EBUSY
Device or resource busy
So just do this:
try:
fp = open("file")
except IOError as e:
print e.errno
print e
Figure out the errno code from there, and you're set.
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.
In my app, I write to an excel file. After writing, the user is able to view the file by opening it. But if the user forgets to close the file before any further writing, a warning message should appear. So I need a way to check this file is open before the writing process. Could you supply me with some python code to do this task?
If all you care about is the current process, an easy way is to use the file object attribute "closed"
f = open('file.py')
if f.closed:
print 'file is closed'
This will not detect if the file is open by other processes!
source: http://docs.python.org/2.4/lib/bltin-file-objects.html
I assume that you're writing to the file, then closing it (so the user can open it in Excel), and then, before re-opening it for append/write operations, you want to check that the file isn't still open in Excel?
This is how you could do that:
while True: # repeat until the try statement succeeds
try:
myfile = open("myfile.csv", "r+") # or "a+", whatever you need
break # exit the loop
except IOError:
input("Could not open file! Please close Excel. Press Enter to retry.")
# restart the loop
with myfile:
do_stuff()
For windows only
None of the other provided examples would work for me when dealing with this specific issue with excel on windows 10. The only other option I could think of was to try and rename the file or directory containing the file temporarily, then rename it back.
import os
try:
os.rename('file.xls', 'tempfile.xls')
os.rename('tempfile.xls', 'file.xls')
except OSError:
print('File is still open.')
You could use with open("path") as file: so that it automatically closes, else if it's open in another process you can maybe try
as in Tims example you should use except IOError to not ignore any other problem with your code :)
try:
with open("path", "r") as file: # or just open
# Code here
except IOError:
# raise error or print
Using
try:
with open("path", "r") as file:#or just open
may cause some troubles when file is opened by some other processes (i.e. user opened it manually).
You can solve your poblem using win32com library.
Below code checks if any excel files are opened and if none of them matches the name of your particular one, openes a new one.
import win32com.client as win32
xl = win32.gencache.EnsureDispatch('Excel.Application')
my_workbook = "wb_name.xls"
xlPath="my_wb_path//" + my_workbook
if xl.Workbooks.Count > 0:
# if none of opened workbooks matches the name, openes my_workbook
if not any(i.Name == my_workbook for i in xl.Workbooks):
xl.Workbooks.Open(Filename=xlPath)
xl.Visible = True
#no workbooks found, opening
else:
xl.Workbooks.Open(Filename=xlPath)
xl.Visible = True
'xl.Visible = True is not necessary, used just for convenience'
Hope this will help
Try this method if the above methods corrupt your excel file.
This function attempts to rename the file with its own name. If the file has already been opened, the edit will be reject by the os and an OSError exception will be raised. It does not touch the inner code so it will not corrupt your excel files. LMK if it worked for you.
def check_file_status(self):
try:
os.rename("file1.xlsx", "file1.xlsx")
print("File is closed.")
except OSError:
print("File is opened.")
if myfile.closed == False:
print("File is still open ################")
Just use this function. It will close any already opened excel file
import os
def close():
try:
os.system('TASKKILL /F /IM excel.exe')
except Exception:
print("KU")
close()
Well, I have made a module that allows you to copy a file to a directory easier. Now, I also have some "try's" and "except's" in there to make sure it doesn't fail in the big messy way and doesn't close the terminal, but I also want it to display different error messages when a wrong string or variable is put in, and end the module, but not the...if I may say, Terminal running it, so I did this:
def copy():
import shutil
import os
try:
cpy = input("CMD>>> Name of file(with extension): ")
open(cpy, "r")
except:
print("ERROR>>> 02x00 No such file")
try:
dri = input("CMD>>> Name of Directory: ")
os.chdir(dri)
os.chdir("..")
except:
print("ERROR>>> 03x00 No such directory")
try:
shutil.copy(cpy, dri)
except:
print("ERROR>>> 04x00 Command Failure")
Problem is that it doesn't end the module if there is no file or directory, only at the finish.
You may be thinking that when an exception is raised, Python just stops what it's doing, but that's not quite true. The except: block actually catches the exception raised, and is supposed to handle it. After an except: block finishes, Python will continue on executing the rest of the code in the file.
In your case, I'd put a return after each print(...). That way, after Python prints out an error message, it will also return from the copy() function rather than continuing to ask for more input.
If you did want to make the module exit on error...
Here's how you'd do it.
def copy():
import shutil
import os
import sys
try:
cpy = input("CMD>>> Name of file(with extension): ")
open(cpy, "r")
except:
sys.exit("ERROR>>> 02x00 No such file")
try:
dri = input("CMD>>> Name of Directory: ")
os.chdir(dri)
os.chdir("..")
except:
sys.exit("ERROR>>> 03x00 No such directory")
try:
shutil.copy(cpy, dri)
except:
sys.exit("ERROR>>> 04x00 Command Failure")
sys.exit(0) (for success) and sys.exit(1) (for failure) are usually used but, since you want to output the error, the above example will output the error string to stderr.
Here's a link for more info on sys.exit().