I'm trying to create a folder, handling the different errors (FileExistsError if the folder already exists and OSError if the folder's name contains illegal characters), but Python seems to always choose the first except block when catching an error no matter which one it is and the order they are.
Is there anything I didn't understand?
import os
from pathlib import Path
def generateSetup(name) :
dir_path = os.path.dirname(os.path.realpath(__file__))
if not Path(dir_path + '/setups').exists() : os.mkdir(dir_path + '/setups')
try : os.mkdir(dir_path + '/setups/' + name)
except FileExistsError : print('The file already exists')
except OSError : print('The name contains illegal characters')
stp_name = input('Enter your setup\'s name :')
generateSetup(stp_name)
There is nothing wrong with your code. It works properly as intended, catches FileExistsError if the directory already exists or OSError if the directory name contains invalid symbols. So I assume the problem is in the way you are testing the code
>>> dloc='tmp/\/b'
>>> try:
... os.mkdir(dloc)
... except FileExistsError:
... print('The file already exists')
... except OSError:
... print('The name contains illegal characters')
...
The name contains illegal characters
we can give any name to directory there is no naming conventions to follow for creating directory through python code.
In this case only the first except block will throw the message if entered name is already a directory name otherwise not.
Related
My program takes in input of the file name and makes some alterations to the file. In case the user enters the wrong name, I don't want my program to crash.
Currently, my code is:
try:
df = pd.read_csv('directory\\%s' % user_input)
except Exception:
[error message]
For some reason, I keep getting the error message even when the file name exists. Is something wrong with my approach?
Whenever possible you should try to be specific with your exception handling. Your code doesn't look quite right.
import os
try:
df = pd.read_csv(os.path.join(directory, user_input))
except IOError as e:
# print e
Might be what you want.
Your file path is formatted wrong.
'directory\\%s' % user_input
When handling the errors that occur when trying to create an existing file or trying to use a file that doesn't exist the OSErrors that get thrown have a subclass (FileExistsError, FileNotFoundError). I couldn't find that subclass for the special case when the filename is too long.
The exact error message is:
OSError: [Errno 36] File name too long: 'filename'
I would like to catch the OSError that occurs when the filename is too long, but only when the filename is too long. I do not want to catch other OSErrors that might occur. Is there a way to achieve this?
Edit: I know that I could check the filename against a length but the maximum filename length varies too much depending on the OS and the filesystem and I don't see a "clean" solution that way.
Simply check errno attribute of caught exception.
try:
do_something()
except OSError as exc:
if exc.errno == 36:
handle_filename_too_long()
else:
raise # re-raise previously caught exception
For readability you may consider using appropriate constant from errno built-in module instead of hardcoded constant.
You can specify just how you want to catch a specific error such as errno.ENAMETOOLONG:
Specific to your question...
try:
# try stuff
except OSError as oserr:
if oserr.errno != errno.ENAMETOOLONG:
# ignore
else:
# caught...now what?
Specific to your comments...
try:
# try stuff
except Exception as err:
# get the name attribute from the exception class
errname = type(err).__name__
# get the errno attribute from the exception class
errnum = err.errno
if (errname == 'OSError') and (errnum == errno.ENAMETOOLONG):
# handle specific to OSError [Errno 36]
else if (errname == 'ExceptionNameHere' and ...:
# handle specific to blah blah blah
.
.
.
else:
raise # if you want to re-raise; otherwise code your ignore
This will grab all exceptions caused by errors in the try. Then it checks if the __name__ matches any specific exception and any additional conditions you want to specify.
You should know there is no getting around the except if an error is encountered unless you specific a concrete exception.
In the following piece of code, some_path is a string that corresponds to a path (may be a relative path)
def editable(some_path):
"""Safely check whether a file is editable."""
delete = not os.path.exists(some_path)
try:
with open(some_path, 'ab'):
return True
except:
return False
finally:
# If the file didn't exist before, remove the created version
if delete:
try:
os.remove(some_path)
except:
pass
In open's docs we read:
If the file cannot be opened, IOError is raised
Is IOError the only possible error I can get (UnicodeError comes to mind, or OSError etc) ?
os.remove docs are even more vague:
If path is a directory, OSError is raised
So what if the file is in use, or protected or...
UPDATE: How about shutil.move ? This seems to raise yet another shutil.Error(StandardError) - if I read the source right
I have the following code:
except(OSError) as (errno, strerror, filename):
print "OSError [%d]: %s at %s" % (errno, strerror, filename)
It runs great unless it meets OSError num. 123 (The file name, directory name, or volume label syntax is incorrect). then I get the following error at the except code line:
ValueError: need more than 2 values to unpack
It is solved by not using the filename attribute. However my requirements prevent me from not using this attribute.
Is there another way?
I have not seen this kind of Exception handling where you are passing the Exception object's attributes to the as clause.
Normally you handle except ExceptionObject as e and handle the attributes as one would normally handle the attributes of an object.
OSError contains a errno attribute is a numeric error code from errno, and the strerror attribute is the corresponding string and for exceptions that involve a file system path (such as chdir() or unlink()), the exception instance will contain a third attribute, filename, which is the file name passed to the function.
import os
try:
os.chdir('somenonexistingdir')
except OSError as e:
print e.errno
print e.filename
print e.strerror
if __name__=="__main__":
fname= raw_input("Please enter your file:")
mTrue=1
Salaries=''
Salarieslist={}
Employeesdept=''
Employeesdeptlist={}
try:
f1=open(fname)
except:
mTrue=0
print 'The %s does not exist!'%fname
if mTrue==1:
ss=[]
for x in f1.readlines():
if 'Salaries' in x:
Salaries=x.strip()
elif 'Employees' in x:
Employeesdept=x.strip()
f1.close()
if Salaries and Employeesdept:
Salaries=Salaries.split('-')[1].strip().split(' ')
for d in Salaries:
s=d.strip().split(':')
Salarieslist[s[0]]=s[1]
Employeesdept=Employeesdept.split('-')[1].strip().split(' ')
for d in Employeesdept:
s=d.strip().split(':')
Employeesdeptlist[s[0]]=s[1]
print "1) what is the average salary in the company: %s "%Salarieslist['Avg']
print "2) what are the maximum and minimum salaries in the company: maximum:%s,minimum:%s "%(Salarieslist['Max'],Salarieslist['Min'])
print "3) How many employees are there in each department :IT:%s, Development:%s, Administration:%s"%(
Employeesdeptlist['IT'],Employeesdeptlist['Development'],Employeesdeptlist['Administration'])
else:
print 'The %s data is err!'%fname
When I enter a filename, but it didn't continue, why? If I enter a file named company.txt, but it always show the file does not exist. why?
I can give you some hints which can help you to resolve problem better
Create a function and call it in main e.g.
if __name__=="__main__":
main()
Don't put whole block under if mTrue==1: instead just return from function on error e.g.
def main():
fname= raw_input("Please enter your file:")
try:
f1=open(fname)
except:
print 'The %s does not exist!'%fname
return
... # main code here
Never catch all exceptions , instead catch specific exception e.g. IOError
try:
f1 = open(fname):
except IOError,e:
print 'The %s does not exist!'%fname
otherwise catching all exception may catch syntax error or mis-spelled names etc
Print the exception you are getting, it may not always be file not found, may be you don't have read permission or something like that
and finally your problem could be just that, file may not exist, try to input full path
Your current working directory does not contain company.txt.
Either set your current working directory or use an absolute path.
You can change the working directory like so:
import os
os.chdir(new_path)
In addition to be more specific about which exceptions you want to catch you should considered capturing the exception object itself so you can print a string representation of it as part of your error message:
try:
f1 = open(fname, 'r')
except IOError, e:
print >> sys.stderr, "Some error occurred while trying to open %s" % fname
print >> sys.stderr, e
(You can also learn more about specific types of Exception objects and perhaps handle
some sorts of exceptions in your code. You can even capture Exceptions for your own inspection from within the interpreter so you can run dir() on them, and type() on each of the interesting attributes you find ... and so on.