I'm trying to write an error handling class for my application. Is it necessary to include the full path to the error handler every time? Below is my code.
appname/appname/model/error.py
class UserError(Exception):
""" User errors
"""
def __init__(self, value):
self.value = value
def __str__(self):
return repr(self.value)
My class function:
from error import UserError
def doSomething(
""" Some function
"""
if (value == 2):
pass
else:
raise UserError('Value is not 2')
That is called from my application as follows:
from error import UserError
try:
print names['first']
except appname.model.error.UserError as e:
print e
When raised:
>> appname.model.error.UserError: 'No file specified'
Do I have to refer to this as "appname.model.error.UserError" all the time? Or is there a way to just refer to this error as UserError or even error.UserError? Where to I adjust the scope of this? Seems like not a good idea in case I change the directory structure (or even name) of my application, no?
You could do this:
from appname.model.error import UserError
Related
Here is the original class:
class Original(object):
def __ init__(self, path):
self.xml = None
self.path = path
self.convert() # <----- I can't modify anything in my class
def convert(self):
#some code here
self.xml = external_api_call # <------------this generates objects for this property
self.transform()
def transform(self):
#some code
if not self._xml:
raise Exception('None value')
for project in self.xml.projects:
try:
value = getattr(project, "name")
except AttributeError:
raise Exception('AttributeError')
print('Yes it worked')
I want to have 100% coverage therefore, i tried to generate mock objects for external api calls. Unfortunately while using a mock object it never raises any exception.
with mock.patch('something.Original', autospec=True) as mock_object:
mock_object.xml = None
mock_object.transform()
It should generate an exception but it doesn't. I have also tried different approaches e.g side_effect property of mock object.
mock_object._xml.return_value
#patch('something.Original')
def test_case_1(Original):
Original.xml.side_effect = Exception()
Original.transform()
I'm trying to override flask_jsonrpc's formatter method:
from flask_jsonrpc import exceptions
def override_jsonrpc_error_formatter(app):
#property
def json_rpc_format(self):
return ErrorFormatter.format_error(self)
exceptions.Error.json_rpc_format = json_rpc_format
override_jsonrpc_error_formatter function is called in a different file then.
Everything works, but pycharm shows me a warning for the last string, saying: "property json_rpc_format cannot be set". Why is it happening? Do I need to override it in a different way?
So, you import the exceptions from the flask_jsonrpc package.
In the package, you can find these lines:
class Error(Exception):
"""Error class based on the JSON-RPC 2.0 specs
http://groups.google.com/group/json-rpc/web/json-rpc-1-2-proposal
code - number
message - string
data - object
status - number from http://groups.google.com/group/json-rpc/web/json-rpc-over-http JSON-RPC over HTTP Errors section
"""
code = 0
message = None
data = None
status = 200
def __init__(self, message=None, code=None, data=None):
"""Setup the Exception and overwrite the default message
"""
super(Error, self).__init__()
if message is not None:
self.message = message
if code is not None:
self.code = code
if data is not None:
self.data = data
#property
def json_rpc_format(self):
"""Return the Exception data in a format for JSON-RPC
"""
error = {
'name': text_type(self.__class__.__name__),
'code': self.code,
'message': '{0}'.format(text_type(self.message)),
'data': self.data
}
if current_app.config['DEBUG']:
import sys, traceback
error['stack'] = traceback.format_exc()
error['executable'] = sys.executable
return error
So basically, you're trying to overwrite a property of the Error class from the flask_jsonrpc package, which is not allowed, because it's an unsettable property.
If you instead want to overwrite it, I think you should inherit from it using a different class, and either import that directly or connect it back to the module.
E.g.:
class myCustomError(exceptions.Error):
#property
def json_rpc_format(self):
return do_some_custom_logic_here()
You need to read about setters
In you case I would do something like:
class CustomError(Error):
#property
def json_rpc_format(self):
return self._json_rpc_format
#json_rpc_format.setter
def json_rpc_format(self, value):
self._json_rpc_format = value
I'd like to have an exception that always sends an email when raised. As for now, I was planning to put that code into __init():
import sendmail
import configparser
def MailException(BaseException):
"""
sends mail when initiated
"""
def __init__(self, message, config=None):
# Call the base class constructor with the parameters it needs
BaseException.__init__(message)
if config is None:
config = configparser.RawConfigParser()
config.read('mail.ini')
config = config['email']
text = 'exception stack trace + message'
sendmail.sendMail(text=text, config=config['email'], title='Alert')
I'd explicitly like to have the mail-sending here, instead of in every except-block I create. Hence I wonder how to get the stack trace, the code has to be compatible with Python 2.7.
The only thing I could find was traceback, but that apparently only works within the except: realm - or is there a way to implement it within the Exception class? Any other ideas?
Firstly, note that (per the docs) you shouldn't subclass BaseException.
Secondly, rather than implement that logic in the exception itself you could define a new sys.excepthook (see e.g. Python Global Exception Handling), then you get access to the full traceback:
import sys
class MailException(Exception):
pass
def mailing_except_hook(exctype, value, traceback):
if exctype == MailException:
... # do your thing here
else:
sys.__excepthook__(exctype, value, traceback)
sys.excepthook = mailing_except_hook
I have a class object that creates some data fields:
class DataFields(object):
_fields_ = ['field_1', 'field_2', 'data_length']
def __init__(self, data=None):
if data != None:
self.create_fields(data)
def create_fields(self, data):
i = 0
for field in self._fields_:
setattr(self, field, data[i])
i += 1
def get_datalength(self):
return self.data_length
What is the best way to make sure that the get_datalength() function cannot be called unless the data_length field has been created (that is, unless the create_fields() function has been called once).
I've thought about either using a variable that gets initialized in the create_fields and is checked in get_datalength() or try-except inside the get_datalength() function. What is the most Pythonic (or the best) way?
I think the most pythonic way would be to throw an exception:
def get_datalength(self):
try:
return self.data_length
except AttributeError:
raise AttributeError("No length call create_fields first")
Simple reason: There is no way to prevent the user to call this function on the object. Either the user would get a AttributeError and would not understand what is going on, or you provide an own Error class or at least error message.
BTW:
It is not pythonic creating getter methods(there are no such things as 'private members')
If you need to do smaller operation on the value returning it have a look at the #property decorator
#property
def datalength(self):
return do_some_stuff(self.data_length)
By using getattr with default value, you can return None or any value if there is no data_length attribute yet in instance:
def get_datalength(self):
return getattr(self, 'data_length', None)
Using an exception is probably the best way for what you are doing however there are alternatives that may be useful if you will be using this object from an interactive console:
def fn2(self):
print("this is fn2")
class test:
def fn1(self):
print("this is fn1")
self.fn2 = fn2
def fn2(self): # omit this if you want fn2 to only exist after fn1 is called
print("Please call fn1 first")
I wouldn't recommend this for every-day use but it can be useful in some cases. If you omit defining fn2 within the class, then the method fn2 will only be present after fn1 is called. For easier code maintenance you can do the same thing like this:
class test:
def fn1(self):
print("this is fn1")
self.fn2 = self._fn2
def _fn2(self):
print("this is fn2")
def fn2(self): # omit this if you want fn2 to only exist after fn1 is called
print("Please call fn1 first")
If this is to be used inside a module that will be imported then you should either raise an exception or return a valid value like the other answers have suggested.
This can be solved by having a dictionary, as a class variable, with method names as keys.
called['method1']
called['method2']
called['method3']
...
And setting the key in that method call
class SomeClass(obj):
def method1():
called['method1'] = 1
def method2():
if method1 in called:
# continue
If I want the function name I can simply include %(funcName)s in the Formatter. But how do I get the name of the class containing the logging call instead?
I've gone through the documentation for logging, but I can't find any mentioning of it.
For a rather easy, pythonic way to get the class name to output with your logger, simply use a logging class.
import logging
# Create a base class
class LoggingHandler:
def __init__(self, *args, **kwargs):
self.log = logging.getLogger(self.__class__.__name__)
# Create test class A that inherits the base class
class testclassa(LoggingHandler):
def testmethod1(self):
# call self.log.<log level> instead of logging.log.<log level>
self.log.error("error from test class A")
# Create test class B that inherits the base class
class testclassb(LoggingHandler):
def testmethod2(self):
# call self.log.<log level> instead of logging.log.<log level>
self.log.error("error from test class B")
testclassa().testmethod1()
testclassb().testmethod2()
By naming the logger as above, the %(name)s will be the name of your class
example output
$ python mymodule.py
[2016-02-03 07:12:25,624] ERROR [testclassa.testmethod1:29] error from test class A
[2016-02-03 07:12:25,624] ERROR [testclassb.testmethod2:36] error from test class B
Alternative(s)
Non-inheritance
import logging
def log(className):
return logging.getLogger(className)
class testclassa:
def testmethod1(self):
log(self.__class__.__name__).error("error from test class A")
class testclassb:
def testmethod2(self):
log(self.__class__.__name__).error("error from test class B")
testclassa().testmethod1()
testclassb().testmethod2()
You should use extra argument:
views.py
import logging
class SampleClass():
def sample_func(self):
logging.getLogger('info_logger').info('some text', extra={'className': self.__class__.__name__})
logger_settings.py
'format': '%(className)s | %(message)s ',
output log:
INFO | SampleClass | "some text"
There is almost certainly a better way of doing this, but until someone points that out, this will work:
import inspect
class testclass:
def testmethod(self):
log()
def log():
stack = inspect.stack()
try:
print "Whole stack is:"
print "\n".join([str(x[4]) for x in stack])
print "-"*20
print "Caller was %s" %(str(stack[2][4]))
finally:
del stack
testclass().testmethod()
The output of this is the following:
Whole stack is:
[' stack = inspect.stack()\n']
[' f()\n']
['testclass().testmethod()\n']
[' exec code in self.locals\n']
[' ret = method(*args, **kwargs)\n']
None
--------------------
Caller was ['testclass().testmethod()\n']
Yet another approach if you also want the module name:
class MyClass(object):
#property
def logger(self):
return logging.getLogger(f"{__name__}.{self.__class__.__name__}")
def what(self, ever):
self.logger.info("%r", ever)
I personally just tend to name my loggers after classes, as it makes it much easier to track down where a particular message came from. So you can have a root logger named "top", and for the module "a" and class "testclass", I name my logger "top.a.testclass".
I don't see the need to otherwise retrieve the classname, since the log message should give you all the information you need.
#ed's response above, it feels very unpythonic to me and it is not something I would be comfortable with using on production code.
This is a function to make an informative log message using the representation class method:
https://docs.python.org/3/library/functions.html#repr
def log_message(thing: object = None, message: str = '') -> str:
""":returns: detailed error message using reflection"""
return '{} {}'.format(repr(thing), message)
This can be implemented to any class using a mix-in:
class UtilMixin(object):
def log(self, message: str = '') -> str:
""":returns: Log message formatting"""
return log_message(thing=self, message=message)
You can than be associated with a class using multiple inheritance:
class MyClass(object, UtilMixin):
def __repr__(self) -> str:
return '<{}>'.format(self)
pass
Usage
logger.warning(self.log('error message goes here'))