python-dependency-injector
python-dependency-injector copied to clipboard
Better error handling: Re-raise with function reference on error
This PR addresses https://github.com/ets-labs/python-dependency-injector/issues/509
@gen-xu I can not accept the PR: with this change, we generally convert any type of exception to the Exception
. This is a serious API change that can create unexpected problems. I'm thankful for the contribution, but we need to look for another solution to prettify the stack trace.
@gen-xu I can not accept the PR: with this change, we generally convert any type of exception to the
Exception
. This is a serious API change that can create unexpected problems. I'm thankful for the contribution, but we need to look for another solution to prettify the stack trace.
I fully agree with your concern.
The reason why it is hard to debug on errors like that is mainly because cython doesn't add locals variables to the traceback object corresponding to the exception instance. see also: cython docs. So, even with good package like traceback_with_variables
(which basically iterate over Exception.__traceback__.tb_frame.f_locals
to print variables) we wouldn't be able to know the name of the callable object.
So I am wondering if adding locals manually to the e.__traceback__.tb_frame.f_locals
would work in this case without breaking API.
I have added a new commit to the PR.
from dependency_injector.containers import DeclarativeContainer
from dependency_injector.providers import Callable, Configuration, Singleton
class A:
def __init__(self, config) -> None:
pass
class B:
def __init__(self, config) -> None:
pass
class SomeContainer(DeclarativeContainer):
config = Configuration()
a = Singleton(A, config)
b = Singleton(B)
c = Callable(print, a, b)
For the code example above, after this change, the new stacktrace would be something like this
|
|
After | Before |
---|---|
|
|
and with the help of traceback_with_variables
|
|
After | Before |
---|---|
|
|
I have added a new commit to the PR.
@gen-xu my apologies for the super delayed feedback. Thanks a lot for working on this.
I think we provide too much noise if we go that way:
Traceback with variables (most recent call last):
File "C:\Users\Gen\Repos\python-dependency-injector\exp.py", line 21, in <module>
s.c()
__name__ = '__main__'
__doc__ = None
__package__ = None
__loader__ = <_frozen_importlib_external.SourceFileLoader object at 0x00000248EF47A100>
__spec__ = None
__annotations__ = {}
__builtins__ = <module 'builtins' (built-in)>
__file__ = 'C:\\Users\\Gen\\Repos\\python-dependency-injector\\exp.py'
__cached__ = None
DeclarativeContainer = <class 'dependency_injector.containers.DeclarativeContainer'>
Callable = <class 'dependency_injector.providers.Callable'>
Configuration = <class 'dependency_injector.providers.Configuration'>
Singleton = <class 'dependency_injector.providers.Singleton'>
print_exc = <function print_exc at 0x00000248F2254EE0>
A = <class '__main__.A'>
B = <class '__main__.B'>
SomeContainer = <class '__main__.SomeContainer'>
s = <dependency_injector.containers.DynamicContainer object at 0x00000248EF9C8FA0>
Could you review #528 ? What do you think if we go that way?
Hi! @rmk135 @gen-xu addition ping for updates)