Open kootenpv opened 7 years ago
Hi - can you post exact errors so I know Im reproducing correctly?
Thanks!
There's just no difference when I import it, it's not actually an error. Try running ipython and importing better_exceptions
Ah, iPython uses a different means to hook into exceptions...
I'll have to do a bit of research about this. iPython doesn't seem to want to install for me at the moment.
+1 on this
You may find some inspiration in the following projects working on exception hooks as well:
The trick is probably to call set_custom_exc(exc_tuple, handler).
(By the way, awesome project!)
If you put this in $HOME/.ipython/profile_default/startup/00-better_exceptions.py
this will enable better_exceptions to be used as the default exception formatter in ipython. Maybe this should go in a contrib
folder or something like that.
from __future__ import print_function
import better_exceptions, sys
ip = get_ipython()
old_show = ip.showtraceback
def exception_thunk(exc_tuple=None, filename=None,
tb_offset=None, exception_only=False):
print("Thunk: %r %r %r %r" % (exc_tuple, filename, tb_offset, exception_only),
file=sys.stderr)
notuple = False
if exc_tuple is None:
notuple = True
exc_tuple = sys.exc_info()
use_better = True
use_better = use_better and (filename is None)
use_better = use_better and (tb_offset is None)
use_better = use_better and (not exception_only)
use_better = use_better and (not isinstance(exc_tuple[0], SyntaxError))
if use_better:
return better_exceptions.excepthook(*exc_tuple)
else:
return old_show(None if notuple else exc_tuple,
filename, tb_offset, exception_only)
ip.showtraceback = exception_thunk
doesnt work with python3
Python 3.5.3 (default, Jan 19 2017, 14:11:04)
Type "copyright", "credits" or "license" for more information.
IPython 5.3.0 -- An enhanced Interactive Python.
? -> Introduction and overview of IPython's features.
%quickref -> Quick reference.
help -> Python's own help system.
object? -> Details about 'object', use 'object??' for extra details.
In [1]: def hey(a):
...: return a/a
...:
In [2]: hey(0)
Thunk: None None None False
example by @Omnifarious rewritten for IPython with python3
put in $HOME/.ipython/profile_default/startup/00-better_exceptions.py
import better_exceptions, sys
ip = get_ipython()
old_show_tb = ip.showtraceback
def exception_thunk(exc_tuple=None, filename=None,
tb_offset=None, exception_only=False):
new_exc_tuple = exc_tuple or sys.exc_info()
if not isinstance(new_exc_tuple[0], SyntaxError):
return print(better_exceptions.format_exception(*new_exc_tuple))
else:
return old_show_tb(exc_tuple, filename,
tb_offset, exception_only)
ip.showtraceback = exception_thunk
WARNING:
as alternative you can use %xmode
magic
Re-writing the example above to work with IPython 3.2.1 and also to handle the case where better_exceptions_module is not present in the system
import sys
try:
import better_exceptions
except ImportError:
better_exceptions = None
def exception_thunk(exc_tuple=None, filename=None,
tb_offset=None, exception_only=False, **kwargs):
new_exc_tuple = exc_tuple or sys.exc_info()
if not isinstance(new_exc_tuple[0], SyntaxError):
return print(better_exceptions.format_exception(*new_exc_tuple))
else:
return old_show_tb(exc_tuple, filename,
tb_offset, exception_only)
if better_exceptions:
ip = get_ipython()
old_show_tb = ip.showtraceback
ip.showtraceback = exception_thunk
I've added **kwargs
because IPython gave that error
TypeError: exception_thunk() got an unexpected keyword argument 'running_compiled_code'
And now to make it work with pdb
mode ;)
@kootenpv It already does.
def foo(a):
import pdb; pdb.set_trace()
assert a == 10
foo(12)
EDIT: ah I see, it doesn't with stepping.
Hi,
I just tried the startup script from @ramast and it works fine, but the better_exceptions output isn't colorized. To make colors work, you can add better_exceptions.SUPPORTS_COLOR = True
to the final if
body (not sure what it will do if the terminal doesn't support colors, probably just print the color codes).
Hi~
if you don't want to see ipython's exception in the Traceback, you can use this one:
import sys
try:
import better_exceptions
except ImportError:
better_exceptions = None
def exception_thunk(exc_tuple=None, filename=None,
tb_offset=None, exception_only=False, **kwargs):
new_exc_tuple = exc_tuple or sys.exc_info()
if not isinstance(new_exc_tuple[0], SyntaxError):
# return print(better_exceptions.format_exception(*new_exc_tuple))
error = better_exceptions.format_exception(*new_exc_tuple).split('\n')
return print("Traceback (most recent call last):\n"+'\n'.join(error[6:]), end='')
else:
return old_show_tb(exc_tuple, filename,
tb_offset, exception_only)
if better_exceptions:
ip = get_ipython()
old_show_tb = ip.showtraceback
ip.showtraceback = exception_thunk
example:
before:
In [1]: def foo(a):
...: assert a > 1
...:
In [2]: foo(0)
Traceback (most recent call last):
File "/xxxx/xxxx/.pyenv/versions/3.6.5/lib/python3.6/site-packages/IPython/core/interactiveshell.py", line 3267, in run_code
exec(code_obj, self.user_global_ns, self.user_ns)
│ │ └ <IPython.terminal.interactiveshell.TerminalInteractiveShell object at 0x10433f438>
│ └ <IPython.terminal.interactiveshell.TerminalInteractiveShell object at 0x10433f438>
└ <code object <module> at 0x1047096f0, file "<ipython-input-2-e3ad81521767>", line 1>
File "<ipython-input-2-e3ad81521767>", line 1, in <module>
foo(0)
└ <function foo at 0x104706f28>
File "<ipython-input-1-41263cb52715>", line 2, in foo
assert a > 1
└ 0
AssertionError: assert a > 1
after:
In [5]: def foo(a):
...: assert a > 1
...:
In [6]: foo(0)
Traceback (most recent call last):
File "<ipython-input-6-7d8d25071659>", line 1, in <module>
foo(0)
└ <function foo at 0x111562950>
File "<ipython-input-5-46c24d49c44a>", line 2, in foo
assert a > 1
└ 0
AssertionError: assert a > 1
i don't know how to pop the exception in the Traceback...so i just delete the line 1 to 6
To make it work with IPython debug, use this improved version:
from __future__ import print_function
import better_exceptions, sys, types
ip = get_ipython()
old_show = ip.showtraceback
def exception_thunk(self, exc_tuple=None, filename=None,
tb_offset=None, exception_only=False, **kwargs):
notuple = False
if exc_tuple is None:
notuple = True
exc_tuple = sys.exc_info()
etype, value, tb = self._get_exc_info(exc_tuple)
use_better = not any ([filename, tb_offset, exception_only, issubclass(etype, SyntaxError)])
if use_better:
return better_exceptions.excepthook(etype, value, tb)
else:
return old_show(None if notuple else exc_tuple,
filename, tb_offset, exception_only, **kwargs)
ip.showtraceback = types.MethodType(exception_thunk, ip)
@issuehunt has funded $70.00 to this issue.
There are a number of code snippets posted in this issue. It seems like this may already work, but not out of the box. Is there a canonical workaround for ipython's different way of handling tracebacks
Ideally one that doesn't require messing with creating a personal ipython startup script. My personal preference would be registering an ipython magic like many other ipython related libraries do. Something like %%better_exceptions
so it can be explicitly turned on/off per cell... But anything is usually an improvement on nothing. So it would be good to just have a clear workaround at all. 😄
Someone mentioned %xmode
in passing and I think it deserves more attention. For those who don't know, %xmode Verbose
will change the builtin exception handler to display variables. It's trying to solve the same problem as better-exceptions
. Wouldn't the best solution be to identify what better-exceptions
has to offer that xmode
doesn't and then integrate those features directly into IPython?
Going a little off-track, it's possible to do better than either in some cases. In GUI environments like Jupyter notebooks and Jupyterlab, one can create an interactive traceback that only shows variables when requested. Django puts them in a collapsible panel:
Flask/werkzeug lets you open a console in any frame:
I don't know if anyone does this, but I think it might be awesome if hovering over a variable name in a traceback displays it.
There's an open issue about this: https://github.com/jupyter/notebook/issues/1247
OK, somewhat coincidentally, an alternative possibility has come up here: https://github.com/ipython/ipython/issues/11827#issuecomment-513001601
In particular:
Ultratb is a real mess and really old. Any refactor to it is welcomed; I've been willing from some time to separate the traceback information extracting from the formatting, to potentially make a nice HTML repr... If we want/can extract these into common packages I'm all for it. There is also https://github.com/qix-/better-exceptions that looks nice; though showing variable values can be a security issue s can't be enabled by default.
Essentially it would be good if there was a package which had a lower level API that returned information about a traceback which a user could easily format in different ways. IPython would be interested in such a package, as would I, and potentially other packages such as Django and Flask.
@Qix- are you interested in this package being refactored to offer such an API? It would then power the existing higher level API which does the formatting, hooks, REPL, etc. The higher level API could also still be useful to other packages, e.g. @Carreau was probably mainly interested in the variable formatting.
I would be happy to work on the coding, and I'm guessing others would too. But I'm concerned by the PRs that are starting to queue up with little/no response. @Qix-, do you still have the time and energy to maintain this repository and review contributions? Would you be able to handle the increased pressure if this became a dependency of IPython? If not, would you be willing to hand the responsibility over to others such as @Delgan? Otherwise I am tempted to write such a package myself from scratch and borrowing bits of code from here.
Hey @alexmojaki, I'm still around - moved around the world about 8 months ago and have just lately been getting back into OSS.
I appreciate the heads up about the ipython issue - I'd be very interested in a more comprehensive package.
As for the neglect, I will be rectifying that in the coming week.
Thanks that is great ! Hope you enjoyed your trip around the world !
Some notes: IPython also support showing variables values in stacktraces; it is disabled by default because we had issues where this was leaking secrets in tracebacks during talks, or to notebooks published on github. Though the way you show it is way nicer than ours!
There are also 2 things that we do, which I believe this does not do yet is 1) show more than 1 line context, and 2) elide when there is a recursion error with N frames repeated X times
.
A more comprehensive package and single-stop-shop is always good. Even better if we can at some point justify movin some of the functionality to core Python :-)
@Carreau I've opened #92 to discuss showing multiple lines in a frame.
Does not appear to work in ipython (at least in emacs)
IssueHunt Summary
### Backers (Total: $70.00) - [ issuehunt](https://issuehunt.io/u/issuehunt) ($70.00) #### [Become a backer now!](https://issuehunt.io/r/Qix-/better-exceptions/issues/10) #### [Or submit a pull request to get the deposits!](https://issuehunt.io/r/Qix-/better-exceptions/issues/10) ### Tips - Checkout the [Issuehunt explorer](https://issuehunt.io/r/Qix-/better-exceptions/) to discover more funded issues. - Need some help from other developers? [Add your repositories](https://issuehunt.io/r/new) on IssueHunt to raise funds. --- IssueHunt has been backed by the following sponsors. [Become a sponsor](https://issuehunt.io/membership/members)