PyQt5 Urllib Dropping Output - python

I'm running a PyQt5 UI that adds IP addresses through REST APIs. When sending operations to my worker Thread (runs a few for loops, and runs a few functions within those loops), whenever I get an exception thrown within the code...it will not print the exact error from json.loads.
My main goal is to get the exact err.read() of the the 4xx or 5xx error I receive, so to tell the user what exactly happened (the 4xx and 5xx errors will output, just not the json.loads(err.read()).)
def patch_object_group (f):
self.api_path = "/api/objects/networkobjectgroups/EXT-SFTPALLOWED/"
self.req = urllib.request.Request(str(server) + self.api_path, json.dumps(self.patch_data_group).encode('utf-8'), headers, method="PATCH") #Default Method is Post
self.base64string = base64.encodestring(('%s:%s' % (username,password)).encode()).decode().replace('\n', '')
self.req.add_header("Authorization", "Basic %s" % self.base64string)
try:
f = urllib.request.urlopen(self.req)#Had to add .request between the url for python 3.
self.status_code = f.getcode()
# print("Status code is {}.".format(self.status_code))
if self.status_code == 204:
print ("The following object was added to the group successfully: {}".format(self.patch_data_group["members.add"][0]["value"]))
jsonoutputlist.append(self.patch_data_group)
except urllib.error.HTTPError as err: #Python3 requires urllib.error.HTTPError to work.
print ("Error received from server: {}. HTTP Status code: {}".format(err.reason, err.code))
In this try statement, with logging and Printouts the code never makes it into the "if" statement...and it appears json.loads(err.read) doesn't actually read the error.
try:
json_error = json.loads(err.read)
if json_error: #Doesn't make it into the if statement when error is received.
print (json.dumps(json_error,sort_keys=True,indent=4, separators=(',', ': ')))
except ValueError:
pass
finally:
if f: f.close()
return (f)
I'm using the following in my main UI (not worker thread) to Emit all stdout's to the UI textbox.
class EmittingStream(QtCore.QObject):
textWritten = QtCore.pyqtSignal(str)
def write(self, text):
self.textWritten.emit(str(text))
def flush(self):
pass
Any assistance would be greatly appreciated.
Thanks,

Found the answer after further testing! json_error was receiving the error as bytes and not a str. I found that in my code I was just passing the ValueError...not error handling appropriately.
except ValueError:
pass
I added in the following:
except (TypeError, ValueError) as e:
print("Error: {}".format(e))
pass
This allowed me to see the exact error was a TypeError.
Found my json_error was actually passing as a byte and not a string. Added .decode() to my code and now it outputs the exact error.
json_error = json.loads(err.read().decode())

Related

How do I print an exception if error in code?

If have a function were I request some data from a website but when I get an error I want to print the error and restart my code. But I don't know the exact code, can please someone help me? This is a code example:
import time
input1 = input("Blabla: ")
def repeat():
try:
if input1 == "123":
raise "Error: 123"
except Exception as e:
print(e)
time.sleep(5) # Wait 5 seconds
repeat() # Rerun code
repeat()
When I run this code I get the error 'exceptions must derive from BaseException'. Can someone help me?
You can't just raise random strings as an exception. If you want to raise a general exception without defining a relevant type, just raise Exception, replacing:
raise "Error: 123"
with:
raise Exception("Error: 123") # The "Error: " should probably be removed
Alternatively, if you can use a more specific error, do so. If 123 is invalid because the value is wrong, use ValueError instead of Exception. If there is some more specific reason, make a subclass to make it easier for others to catch, e.g. (at top level in the module):
class SpecialValueError(ValueError):
pass
so you can do:
raise SpecialValueError("Error: 123")
and people can catch it specifically, or via plain except ValueError:, except Exception:, etc.
Right now you are printing the error object's str while you need to print it's representation
Try this:
def repeat():
try:
if input1 == "123":
raise Exception("Error: 123") # You need to use an Exception class
except Exception as e:
print(repr(e)) # Notice I added repr()
time.sleep(5)
repeat()
Exception's Representation vs Exception's String
String:
try:
raise Exception("Exception I am!")
except Exception as e:
print(e)
# Output: Exception I am!
Representation:
try:
raise Exception("Exception I am!")
except Exception as e:
print(repr(e))
# Output: Exception('Exception I am!')

python - move on after exception and raise it afterwards

I think this should be a bit tricky but somehow feasible, but I need help.
I'd like to execute two functions from within my main() func.
I'd like to be able to catch exceptions from the two separately, but still being able to execute both and get the result of at least one of them if the other raises an exception.
Let's say I have:
def foo():
raise TypeError
def bar():
return 'bar'
If I do (adapted from here):
def multiple_exceptions(flist):
for f in flist:
try:
return f()
except:
continue
def main():
multiple_exceptions([foo, bar])
main()
main() would return 'bar', but I'd like to be able to still throw the exception from foo() after all. This way, I would still have the result of one of my functions and the information on the error occurred in the other.
You can capture and store the exceptions using 'as', e.g.:
try:
raise Exception('I am an error!')
print('The poster messed up error-handling code here.') #should not be displayed
except Exception as Somename:
print(Somename.message)
# you'll see the error message displayed as a normal print result;
# you could do print(stuff, file=sys.stderr) to print it like an error without aborting
print('Code here still works, the function did not abort despite the error above')
...or you can do:
except Exception as Somename:
do_stuff()
raise Somename
Thanks for the comments.
I solved by doing this:
def multiple_exceptions(flist):
exceptions = []
for f in flist:
try:
f()
except Exception as e:
exceptions.append(e.message)
continue
return exceptions
def main():
multiple_exceptions([foo, bar])
error_messages = main() # list of e.messages occurred (to be raised whenever I want)
Then I can raise my exception like e.g. raise Exception(error_messages[0]) (I only care about the first in this case let's say).

How to handle exception in Tornado

I am not sure if this is a python question or a Tornado question. But I am struggling to figure out how I can handle an exception if something fails.
Here is the snippet of code:
class iQHandler(myBaseHandler):
#tornado.gen.coroutine
def _initialize(self):
param1 = self.get_argument('media', None)
if not param1:
raise tornado.web.HTTPError(404)
# default the Output parameter to JSON format.
outputFormat = self.get_argument('output', 'json', False)
try:
res = yield self._findfiles(param1)
except Exception, e:
# What do I do here?
print ("Error in _initialize() routine --> ", e)
# The variable, res, doesn't have any value if there is an exception thrown.
raise tornado.gen.Return(res)
#tornado.web.asynchronous
#tornado.gen.coroutine
def get(self):
response = yield self._initialize()
self.clear()
self.finish(response)
How will I go about either raising an exception and returning a value back to the previous routine? Thanks.
This is a python question. The try except block is fine. You can reraise the same exception by saying raise in the except block without anything after raise. That is, replace
raise tornado.gen.Return(res)
by
raise
Note the indent to keep the raise in the except block.

Python try/except not working

Trying to get the try/except statement working but having problems. This code will take a txt file and copy the file that is in location row 0 to location of row 1. It works however if i change one of the paths to invalid one it generates an error ftplib.error_perm however the except command is not picking up and everything stops. What am i doing wrong? Python 2.4
import csv
import operator
import sys
import os
import shutil
import logging
import ftplib
import tldftp
def docopy(filename):
ftp = tldftp.dev()
inf = csv.reader(open(filename,'r'))
sortedlist = sorted(inf, key=operator.itemgetter(2), reverse=True)
for row in sortedlist:
src = row[0]
dst = row[1]
tldftp.textXfer(ftp, "RETR " + src, dst)
def hmm(haha):
result = docopy(haha);
try:
it = iter(result)
except ftplib.error_perm:
print "Error Getting File"
if __name__ == "__main__":
c = sys.argv[1]
if (c == ''):
raise Exception, "missing first parameter - row"
hmm(c)
The except clause will only catch exceptions that are raised inside of their corresponding try block. Try putting the docopy function call inside of the try block as well:
def hmm(haha):
try:
result = docopy(haha)
it = iter(result)
except ftplib.error_perm:
print "Error Getting File"
The point in the code which raises the error must be inside the try block. In this case, it's likely that the error is raised inside the docopy function, but that isn't enclosed in a try block.
Note that docopy returns None. As such, you will raise an exception when you try to make an iter out of None -- but it won't be a ftplib.error_perm exception, it'll be a TypeError
If you are not sure of what exception will occur, the use the code below, because if especifies for example: except StandardError: and is not that error the exception will not be process.
try:
# some code
except Exception: # Or only except:
print "Error" # Python 3: print("Error")
I know the OP is ancient, but for folks desperate for answers on this question. I had a similar issue, depending on your IDE, if you have a breakpoint on any of the lines with specific exceptions etc, this can conflict and stop try/except executing.
I noticed global exception may not works, e.g. , Ctrl+C when epub.py module perform urllib3 connection trigger KeyboardInterrupt but not able to catch in main thread, the workaround is put my clean up code inside finally, e.g.:
try:
main()
except Exception as e:
clean_up_stuff() #this one never called if keyboard interrupt in module urllib3 thread
finally: #but this work
clean_up_stuff()
This example is generic for Python3.3+, when decorating a generator function, a decorated generator returns successfully, thus not entering the decorators except, the magic happens with yield from f thus wrapping the yieldable within the decorator:
from types import GeneratorType
def generic_exception_catcher(some_kwarg: int = 3):
def catch_errors(func):
def func_wrapper(*args, **kwargs):
try:
f = func(*args, **kwargs)
if type(f) == GeneratorType:
yield from f
else:
return f
except Exception as e:
raise e
return func_wrapper
return catch_errors
Usage:
#generic_exception_catcher(some_kwarg=4)
def test_gen():
for x in range(0, 10):
raise Exception('uhoh')
yield x
for y in test_gen():
print('should catch in the decorator')

Python logging exception

I'm currently writing a wrapper class. I want to be able to log exceptions properly but allow calling methods to be aware of exceptions which occur. My class looks like this:
import logging
log = logging.getLogger('module')
class MyAPIWrapper(library.APIClass):
def __init__(self):
self.log = logging.getLogger('module.myapiwrapper')
def my_wrapper_method(self):
try:
response = self.call_api_method()
return response.someData
except APIException, e:
self.log.exception('Oh noes!')
raise e #Throw exception again so calling code knows it happened
I'm a bit dubious about catching and exception just to log it and then re-raising it so the calling code can do something about it. What's the proper pattern here?
There is nothing wrong with catching to log. However, I'd recommend:
try:
response = self.call_api_method()
except APIException, e: # or 'as e' depending on your Python version
self.log.exception('Oh noes!')
raise #Throw exception again so calling code knows it happened
else:
return response.someData
By just doing a bare raise you preserve the full traceback info. It's also more explicit to put code that will only happen if you don't have an exception in the else clause, and it's clearer what line you're catching an exception from.
It would also be fine for the calling class to do the logging if it's handling the error anyway, but that may not be convenient for your app.
Edit: The documentation for try ... except ... else ... finally is under compound statements.
That method is correct, although instead of raise e you should just use raise, which will automatically re-raise the last exception. This is also one of the rare cases where using a blanket except is considered acceptable.
Here is an example very similar to what you are doing from the Python docs on Handling Exceptions:
The last except clause may omit the exception name(s), to serve as a wildcard. Use this with extreme caution, since it is easy to mask a real programming error in this way! It can also be used to print an error message and then re-raise the exception (allowing a caller to handle the exception as well):
import sys
try:
f = open('myfile.txt')
s = f.readline()
i = int(s.strip())
except IOError as (errno, strerror):
print "I/O error({0}): {1}".format(errno, strerror)
except ValueError:
print "Could not convert data to an integer."
except:
print "Unexpected error:", sys.exc_info()[0]
raise
You can just extend the standard Exception class and add the logger into there.
Like this:
class LoggedException(Exception):
""" An exception that also logs the msg to the given logger. """
def __init__(self, logger: logging.Logger, msg: str):
logger.error(msg)
super().__init__(msg)

Categories