Handling COMError in Python? - python-3.x

Running my script, I get the following error for some files:
COMError: (-2146822496, None, ('The file appears to be corrupted.',
'Microsoft Word', 'wdmain11.chm', 25272, None))
I have imported comtypes, and I wish to do an exception when this error occurs, so I do the following:
try:
code...
except comtypes.COMError:
pass
But it seems that Python does not recognize the exception, as it produces the same COMError as before.
Any suggestions on how to solve this problem? Thanks.

You probably need to show some more of your code in order for anyone to help you. I've run into a similar issue, but my application is a little different. I'll try my best to assist.
You need to actually handle the error that occurs.
So when you get the exception, you need to do something like this:
assuming this is your error:
COMError: (-2146822496, None, ('The file appears to be corrupted.', 'Microsoft Word', 'wdmain11.chm', 25272, None))
except comtypes.COMError as ce:
# get the error information
target_error = ce.args # error in a tuple form
# target_error[0] -> -2146822496
# target_error[1] -> None
# target_error[2] -> 'The file appears to be corrupted.', 'Microsoft Word', 'wdmain11.chm', 25272, None
# target_error[2] is another tuple made up of
# [2][0] -> 'The file appears to be corrupted.'
# [2][1] -> 'Microsoft Word'
# [2][2] -> 'wdmain11.chm'
# [2][3] -> 25272
# [2][4] -> None
if target_error[2][0] == 'The file appears to be corrupted.':
print("# handle your error here inside this if statement")
The point is that once you get the actual error, you can then do something to handle it accordingly.
Again, without seeing your code its difficult to offer any more advice, but you could handle the error based on the Application Type ('Microsoft Word') or the error code ('The file appears to be corrupted.')

Related

Declaring None type exception

I want to define a custom Exception class for the NoneType error in python inheriting from Exception class. I expect the code below to do such a thing for me but no success. Is there any way to do this?
class NoneTypeException(Exception):
pass
try:
image = cv2.imread("/path/")
gray = cv2.cvtColor(image.copy(), cv2.COLOR_BGR2GRAY) #exception should be raised here
...
except NoneTypeException:
raise NoneTypeException("Image not found") # and should be caught here
I want to the try except block raise the NoneTypeException. Any way?
While you can declare an exception to represent whatever you want, existing code won't raise it for you. In specific, operations on None already raise some well-defined errors and you cannot replace them. Strictly speaking, you cannot get the desired behaviour.
If you know that a certain section of code is vulnerable to None values, you can catch the generic Exception and raise a specific one. This hinges on the assumption that None is the only bogus value you might get:
class NoneTypeException(Exception):
pass
try:
image = cv2.imread("/path/")
gray = cv2.cvtColor(image.copy(), cv2.COLOR_BGR2GRAY)
...
except AttributeError as err: # handle generic exception from action on ``None``
raise NoneTypeException("Image not found")
Take note that this is rarely what you should be doing - the None value is a symptom, not the cause of the error. It would be more appropriate to raise a FileNotFoundError.
Since None can trigger errors anywhere, it is easier to protect against it at its origin. Checking for identity with None is very cheap:
try:
image = cv2.imread("/path/")
if image is None: # verify value immediately
raise NoneTypeException()
# safely work with image
gray = cv2.cvtColor(image.copy(), cv2.COLOR_BGR2GRAY)
...
except NoneTypeException:
raise FileNotFoundError('image not found')

Why do the code shows tons of error whenever i type in alphabet input

I am new to python and I have an upcoming assignment that creates a menu that creates a function whenever the users enter the input. Here is the problem, whenever I enter a number the code shows a normal invalid option. For alphabetic input, however, it started to appear tons of errors. Does anyone know how to solve this issue
import turtle
wn = turtle.Screen()
poly = turtle.Turtle()
wn.setup(1000, 600)
poly.pensize(2)
poly.fillcolor('lightblue')
poly.penup()
poly.goto(-400, 15)
poly.pendown()
def menu():
print(' *********************************')
print('1. Draw polygons')
print('2. Draw a flower')
print('3. Exit')
task = int(input('Enter an option (1/2/3): '))
return task
def draw_shape(t, sides):
for i in range(0, sides):
t.forward(50)
t.stamp()
t.left(360 / sides)
t.forward(50)
def draw_flower(t, sides):
for i in range(0, sides):
t.left(90)
t.forward(100)
t.left(137.5)
t.forward(60)
t.left(80)
t.forward(70)
das = menu()
if das == 1:
for angle in [10, 9, 8, 7, 6, 5, 4, 3]:
poly.penup()
poly.forward(100)
poly.pendown()
poly.begin_fill()
draw_shape(poly, angle)
poly.end_fill()
elif das == 2:
poly.pencolor('cyan')
wn.bgcolor('light yellow')
poly.speed(4)
poly.penup()
poly.goto(0, 0)
poly.pendown()
draw_flower(poly, 52)
poly.forward(-100)
elif das == 3:
print('Program exists. Have a nice day')
exit()
else:
print('Invalid option')
. Draw polygons
2. Draw a flower
3. Exit
Enter an option (1/2/3): sa
Traceback (most recent call last):
File "C:/Users/jonny/PycharmProjects/untitled2/Polygon and flowers.py", line 40, in <module>
das = menu()
File "C:/Users/jonny/PycharmProjects/untitled2/Polygon and flowers.py", line 18, in menu
task = int(input('Enter an option (1/2/3): '))
ValueError: invalid literal for int() with base 10: 'sa'
Your Python interpreter is basically telling you that it cannot parse 'sa' into an int, which is to be expected right?
When prompted to enter an option, if you enter sa, input(...) returns exactly that: sa, as a string.
At that point in your script, task = int(input(...)) essentially becomes task = int('sa').
Exceptions
Now put yourself in the shoes of function int(): you receive a string, and you must return an integer.
What do you do when the input string, 'sa' for that matter, does not correctly represent an integer?
You cannot return an integer, because that would imply that you parsed the string successfully.
Returning something else than an integer would make no sense (and would be a pain to work with).
So you throw an exception: the execution flow is interrupted, and a specific kind of object, an exception, is thrown.
Exception handling
When a function throws an exception, it is interrupted: it does not finish running, it does not return anything, and the thrown exception is forwarded to the calling function. If that function decides to catch that exception (i.e. to handle it), then good, the normal execution flow can resume at that point.
If it decides not to handle the exception, then that function is interrupted too and the exception is forwarded yet again to the calling function. It continues in a similar fashion until the exception is caught, or until "no calling function is left", at which point the Python interpreter takes over, halts the execution of your script, and displays info about that exception (which is what happened in your case).
A first solution
If you're new to Python, maybe you shouldn't worry too much about handling exceptions right now. More generally, if you try to handle every possible case when it comes to user input, you're in for a wild ride.
For the sake of completeness though:
In order for your code to do what you expect, replace the das = menu() line with this:
try: # Enter a section of code where exceptions may be thrown
das = menu() # menu() may throw an exception because of the int(...) inside
except: # 'Catch' any exception that was thrown using an `except` block
das = -1 # Set a dummy, invalid value
With this code, if menu() throws an exception (when you enter sa for example), it will be caught: the try block will be interrupted, and the except block will be executed. das will receive value -1, which by the rest of your code is invalid, and thus Invalid option will be displayed. This is much better than having your whole script halted!
On the other hand, if no exception is thrown by menu(), the try block will reach its end normally, and the except block will not be executed.
A better solution
However, this is not ideal. The exception should not be handled around menu(), it should be handled around int(...) inside your menu function.
You could do this as an exercise: first handle the exception inside menu, and then try to loop over the int(input(...)) statement until a valid value is entered by the user.
There again, exception handling is not necessarily trivial and can be hard to get right, especially for beginners. So don't get frustrated if it seems like a not-so-useful overcomplication to you, there will come a point where you realize you can't go without them.
You can read more about exceptions here: https://www.w3schools.com/python/python_try_except.asp or here if you want a more comprehensive tutorial: https://docs.python.org/3/tutorial/errors.html
Hope this helps. :)

Write a program which gives an input from the user by asking 'Give me an input:'

Write a program which gets an input from the user by asking 'Give me an input:',and passes this string to 'silly_function' if the function returns without an error.simply print whatever it returned. However: if the function produces a ValueError,the program should instead print'I cannot use this value'; if the function produces a TypeError,the program should instead print 'Invalid input'
def silly_function(a):
a = input('Give me an input')
try:
sily_function(a)
except ValueError:
print('I cannot see this value')[enter image description here][1]
Let's try this together.
Code Analysis
def silly_function(a):
a = input('Give me an input')
this is fine, it will prompt the user for an input**
try:
silly_function(a)
Why do you need to call silly_function again ? I don't think that was the intended behavior ?
Also silly_function doesn't do anything that will terminate the recursion or generate an error , so this is bound to break.
except ValueError:
print('I cannot see this value')[enter image description here][1]
Suppose this is a typo, but see != useand you are only handling one error and not the other one.
Suggestion
Let's right in pseudocode a bit of help
def error_handling_function(a):
a = input('Give me an input')
try:
silly_function(a)
except #input error here:
#handle error here
except #input error here:
#handle error here
def silly_function(a):
#write code that can break and generate the two error you are looking for

Python IMAP4 append fails silently

When appending a message to a folder that doesn't exist, there is no error thrown. It's hard to imagine that this is intended, what am I doing wrong?
mailbox = imaplib.IMAP4_SSL(host="foo")
mailbox.login("foo", "bar")
try:
mailbox.append("DOES_NOT_EXIST", '', imaplib.Time2Internaldate(time.time()), str(mail).encode("utf-8"))
except:
# Expecting to fail here, but it doesn't
# Message doesn't show up in any other folder either (expectedly)
As rightfully stated in the comments, this is actually intended behaviour indeed and documented.
Each command returns a tuple: (type, [data, ...]) where type is usually 'OK' or 'NO', and data is either the text from the command response, or mandated results from the command.
One way to catch the error therefore is:
status, data = mailbox.append("DOES_NOT_EXIST", '', imaplib.Time2Internaldate(time.time()), str(mail).encode("utf-8"))
if status == "NO":
# Catch it here

QStatusBar.showMessage issue:

I have got 2 situation when trying to call QStatusBar.showMessage().
- 1st: Got error: TypeError: 'QStatusBar' object is not callable
- 2nd: It does not effect and nothing happen. I got a blank status bar, without any error message.
Here the detail:
The MainWindow class:
self.statusbar = QtGui.QStatusBar(MainWindow)
self.statusbar.setObjectName(_fromUtf8("statusbar"))
MainWindow.setStatusBar(self.statusbar)
This module has been imported to the main file. Then, in the main file, I have called QtGui.QStatusBar's showMessage() method, and got two following issues.
1. TypeError: 'QStatusBar' object is not callable
I have used following code statement to call QtGui.QStatusBar's showMessage() method:
self.ui.statusbar().showMessage("You have selected: %s" % self.filename, msecs= 5)
2. A blank statusbar; no effect and there's any error message.
I have used this code statement:
self.ui.statusbar.showMessage("You have selected: %s" % self.filename, msecs= 5)
I haven't got any error, but it's also take no effect.
Someone can help me to figure out that what I have wrong and how to fix it? Thank you!
You use msecs= 5.
This means "show the message for 5 milliseconds"!
Please try with msecs=5000.
You need to remove the '()' behind 'statusbar' because it is isn't a method.

Resources