I made a Python 2.7.9 script which downloads some photos from the web using urllib.urlretrieve. I made a simple error dictation using the try and except commands, like so:
try:
urllib.urlretrieve("http://example.com/image.jpg", "1.jpg")
except IOError:
print "Could not connect to 'example.com'!"
However, I realized that IOError could be also raised when no space left on the the harddrive. I want to detect what cause the raise of the IOError (could not connect to example.com/no space left), and display the correct error message.
How can I do so? Thanks!
As zoosuck said, you could differentiate between errors with more than one except-Statement. If you want to differentiate between IOErrors, take a look at the documentation of IOError. It reveals that IOError has an attribute "errno". You can use the errno module (https://docs.python.org/2/library/errno.html) to identify the cause:
import urllib
import errno
try:
urllib.urlretrieve("http://example.com/image.jpg", "1.jpg")
except IOError, e:
if e.errno == errno.ENOSPC:
print "No space left on device"
else:
print "Could not connect to 'example.com'!"
Related
I have a script which uses pygetwindow module to do some operations on a specific window. While the script runs, I get the following exception:
File "C:\Program Files (x86)\Python38-32\lib\site-packages\pygetwindow\_pygetwindow_win.py", line 237, in activate
_raiseWithLastError()
File "C:\Program Files (x86)\Python38-32\lib\site-packages\pygetwindow\_pygetwindow_win.py", line 97, in _raiseWithLastError
raise PyGetWindowException('Error code from Windows: %s - %s' % (errorCode, _formatMessage(errorCode)))
pygetwindow.PyGetWindowException: Error code from Windows: 0 - The operation completed successfully.
I'm okay with the exception occurring but I want to catch this exception explicitly. I have done the following to try and catch this exception:
try:
#implementation
except pygetwindow.PyGetWindowException:
#handle exception
and
try:
#implementation
except PyGetWindowException:
#handle exception
Neither of the above catches the exception. If I use either of the above, I get another exception:
NameError: name 'PyGetWindowException' is not defined
or
NameError: name 'pygetwindow' is not defined
I don't want to catch the general Exception and then handle it since in case of other exceptions, I want to handle it differently. Is there something wrong in how I'm trying to catch this exception or is there a way to avoid this exception altogether?
EDIT: To be very clear, I have already imported pygetwindow.
You should have import pygetwindow at the begging of your script. It complains about not knowing what pygetwindow is.
Update
From the source file, it was clear that in order to use PyGetWindowException, you need to import the exception specifically (and not just import pygetwindow). Therefore, in order to catch the exception, one will have to do:
from pygetwindow import PyGetWindowException
After this import, you can use the exception in the normal way:
try:
#implementation
except PyGetWindowException:
#handle exception
Update 2
Another general way to do this would be to get the exception name from general exception and compare.
try:
try:
#implementation
except Exception as e:
if e.__class__.__name__ == 'PyGetWindowException':
#handle exception
else:
raise e
except Exception as e:
#handle other exceptions except pygetwindow exception
Original answer (not recommended)
Found a way to solve this question in this answer.
From the source of pygetwindow, it was clear that, whenever PyGetWindowException is raised, it is accompanied by the text:
"Error code from Windows:"
which indicates the error code given by Windows.
Based on this information, I did the following:
try:
try:
#Implementation
except Exception as e:
if "Error code from Windows" in str(e)
# Handle pygetwindow exception
else:
raise e
except Exception as e:
#handle other exceptions
This is another way (although the first one and second one are the correct and straightforward solutions) to solve the problem.
I have been trying to capture an exception that returns the message "Error in file!" when reading from a file in Python.
I had managed to catch the error when the file isn't existing, but unfortunately I couldn't manage to capture the error when there is an error in a file.
Any suggestions?
try:
# ...
except IOError:
print("Error opening file!")
except Exception:
print("Error in file!")
raise
You can track the exception to find out what exactly went wrong in the try-block, so you can handle the new error.
In order to do this, just print details of the exception:
try:
....
except Exception as f:
print(f.__class__)
print(str(f))
This will give you the class of the error (e.g. NameError) and the specific error the program encountered. So, you can handle it with an additional except-clause or debug the code.
I am trying this code:
try:
res = subprocess.Popen('bgpq3 -4 {} -m 24 -l {}'.format('MAIyNT-
AS38082','12414'), shell=True,
universal_newlines=True,
stdout=subprocess.PIPE).communicate()[0]
except Exception:
print("Wrong")
#do this code
The output is ?
ERROR:Unable to parse prefix 'MAIyNT-AS38082', af=2 (inet), ret=0
ERROR:Unable to parse prefix MAIyNT-AS38082
ERROR:Unable to add prefix MAIyNT-AS38082 (bad prefix or address-family)
so i am not able to use Error handling!!
Any Idea?
when you write except Exception: you are not catching all the exception: the system exit errors and OS errors (as BaseException, SystemExit, KeyboardInterrupt and GeneratorExit) are excluded.
Most of the exceptions of subprocess are OSError.
Since you did not report the full traceback of the error, I may only assume that you're getting one of these errors, and you can catch them using:
except subprocess.CalledProcessError:
or
except OSError:
as PEP 8 suggest, you should NOT use except: alone, even if it will work in your case.
As a rule of thumb, always catch the exact exception you espect to be raised!
You're only handling errors of type exception here. You only need to use except:. This way you're catching all errors that occur in the code.
try:
#your code
except Exception as e:
#handle the exception
For more information refer to the docs I got from a quick google ;)
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.
I need to obtain the error number from an error that has occurred in Python.
Ex; When trying to transfer a directory via the Paramiko package, an error is caught with this piece of code:
try:
sftp.put(local_path,target_path)
except (IOError,OSError),errno:
print "Error:",errno
For which I get the output,
Error: [Errno 21] Is a directory
I want to utilize the error number to go into some more code to transfer the directory and the directory contents.
Thanks for clarifying your question.
Most Exceptions in Python don't have "error numbers". One exception (no pun intended) are HTTPError exceptions, for example:
import urllib2
try:
page = urllib2.urlopen("some url")
except urllib2.HTTPError, err:
if err.code == 404:
print "Page not found!"
else:
...
Another exception (as noted by bobince) are EnvironmentErrors:
import os
try:
f=open("hello")
except IOError, err:
print err
print err.errno
print err.strerror
print err.filename
outputs
[Errno 2] No such file or directory: 'hello'
2
No such file or directory
hello
If you're talking about errno.h error numbers, you can get them from the errno property on the exception object, but only on EnvironmentError (which includes OSError, IOError and WindowsError).
Specifically on WindowsError you'll also get a winerror property with a Windows-specific error number. (You don't often see one of these though, as Python uses the Win32 API directly relatively rarely.)
There is also the errno package, which allows working with error codes with out having to handle magic numbers in the code. See an example here: Are Python error numbers associated with IOError stable?