GithubHelp home page GithubHelp logo

tbvaccine's Introduction

TBVaccine

TBVaccine is a utility that pretty-prints Python tracebacks. It automatically highlights lines you care about and deemphasizes lines you don't, and colorizes the various elements in a traceback to make it easier to parse.

Here are some screenshots. This is the before:

misc/before.png

And this is the after:

misc/after.png

If you add the hook or call TBVaccine in your code, it can also print all variables in each stack frame. That is, it turns this:

misc/before-vars.png

into this:

misc/after-vars.png

Installation

To install, use pip:

pip install tbvaccine

You are done!

Global usage

You can have TBVaccine insert itself all up in your system and stick its tentacles in all your libraries, like a cute, useful Cthulhu. That way, every single Python traceback in your system will be pretty. Just set the TBVACCINE environment variable to 1, and you're done.

E.g. for bash:

export TBVACCINE=1

Or fish:

set -x TBVACCINE=1

If you want to prettify tracebacks even when stderr is not a tty, set TBVACCINE_FORCE to 1:

export TBVACCINE=1
export TBVACCINE_FORCE=1
python -c '1/0' 2>&1 | cat  # pretty!

NOTE: If you're on Ubuntu, you most likely have Apport installed, which overrides TBVaccine's hook with its own. To disable Apport for Python, delete a file named /etc/python<version>/sitecustomize.py. Note that this will disable Apport for Python, and you won't be asked to submit info to Ubuntu when Python programs crash any more. For some, this is a good thing.

Usage as a command-line utility

TBVaccine can be used from the command line several ways.:

python -m tbvaccine myscript.py

Or just pipe STDERR into it from the program you want to watch:

./myscript.py 2>&1 | tbvaccine

And all the tracebacks will now be pretty!

Usage as a Python library

There are various ways to use TBVaccine as a Python library.

Initialize it like so:

from tbvaccine import TBVaccine
tbv = TBVaccine(
    code_dir="/my/code/dir",
    isolate=True
)

code_dir marks the directory we code about. Files under that directory that appear in the traceback will be highlighted. If not passed, the current directory, as returned by os.getcwd() will be used.

If isolate is False, all lines are colorized, and code_dir is ignored.

If show_vars is False, variables will not be printed in each stack frame.

To use it in an except block:

from tbvaccine import TBVaccine
try:
    some_stuff()
except:
    print(TBVaccine().format_exc())

To make it the default way of printing tracebacks, use add_hook() (which also accepts any argument the TBVaccine class does):

import tbvaccine
tbvaccine.add_hook(isolate=False)

1 / 0

Bam! Instant pretty tracebacks.

Logging integration

You can integrate TBVaccine with logging like so:

class TbVaccineFormatter(logging.Formatter):
    def  formatException(self, exc_info):
        return TBVaccine(isolate=True).format_exc()

sh = logging.StreamHandler()
sh.setFormatter(TbVaccineFormatter('[%(levelname)s] %(asctime)s : %(message)s', '%Y-%m-%d %H:%M:%S'))
logger.addHandler(sh)

Configuration

To configure TBVaccine, open its configuration file in ~/.config/tbvaccine/tbvaccine.cfg (or your operating system's equivalent) and edit it. You can currently configure the color style there by specifying one of the Pygments styles <http://pygments.org/demo/6778888/?style=monokai>.

Epilogue

This library is still pretty new, please contribute patches if something doesn't work as intended, and also please tell your friends about it! Hopefully one day it will be implemented in the Python interpreters themselves.

-- Stavros

tbvaccine's People

Contributors

akittas avatar avamsi avatar avivey avatar azmeuk avatar flying-sheep avatar minchinweb avatar nixjdm avatar skorokithakis avatar szabolcsdombi avatar wataash avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

tbvaccine's Issues

[feature request] settings on displaying local variables

All local variables displayed on each stack frame lead to huge unreadable stack pretty fast.
You could add a setting to display or not display them.
Also, displaying functions and modules does not seem so helpful. You might get rid of them, or add a distinct setting to display them too.

Add hyperlinks to source files in traceback

There is a specification for hyperlinks in terminals

https://gist.github.com/egmontkob/eb114294efbcd5adb1944c9f3cb5feda

It would be good if TBVacine could link to the python files mentioned.

Currently there isn't a way of linking to particular lines, but being able to open a file from the terminal is a nice improvement.

This may be worth gating behind config or envvar in case a terminal doesn't support it (though most should display nothing where the link will be anyway)

Hooked by TBVACCINE=0 is confusing

README says export TBVACCINE=1 hooks tbvaccine, so I expected export TBVACCINE=0 would not hook, but it did.
I think the hook should be done only if TBVACCINE is exactly 1. (but that's a breaking change...)

ipython integration

There's at least a couple problems with this working with ipython.

  1. Exporting the env var seems to have no effect.
  2. This brings the formatting of tbvaccine, and some things, but not the locals I added in the shell.
from tbvaccine import TBVaccine 
try:
    some_stuff()
except:
    print(TBVaccine().format_exc())

imagine this is styled:

Traceback (most recent call last):
  File "<ipython-input-2-6c94a79ed40f>", line 4, in <module>
>   some_stuff()
|     __annotations__ = {}
|     __builtins__    = <module 'builtins' (built-in)>
|     __cached__      = None
|     __doc__         = None
|     __file__        = [path to]/bin/ipython
|     __loader__      = <_frozen_importlib_external.SourceFileLoader object at 0x7f880a16fc88>
|     __name__        = __main__
|     __package__     = None
|     __spec__        = None
|     re              = <module 're' from '[path to]/lib/python3.6/re.py'>
|     start_ipython   = <function start_ipython at 0x7f88069a18c8>
|     sys             = <module 'sys' (built-in)>
NameError: name 'some_stuff' is not defined

  1. This seems to not be any different from a normal exception in ipython. It looks identical either way.
import tbvaccine
tbvaccine.add_hook(isolate=False)

1 / 0

The same seems to hold for at least flask-shell-ipython, which is unsurprising.

Possibly out-of-scope: I have no idea really, but maybe whatever is needed to get this to work would also suffice for Jupyter as well. If we're lucky.

TBVaccine produces insane reporting when Dask or Dask Distributed task crashes

Here is the reproduction:

import tbvaccine
tbvaccine.add_hook(isolate=False)

import dask

def x(arg1=123):
    assert arg1 == 122, "qwe"

if __name__ == '__main__':
    dask.delayed(x)().compute()

The error:

  File "/tmp/env/lib/python3.5/site-packages/dask/async.py", line 272, in _execute_task
    return func(*args2)
  File "qq5.py", line 7, in x
    assert arg1 == 122, "qwe"
|     worker_id                = None
AssertionError: qwe

I don't understand at all where worker_id came from.

Running Dask Distributed, I see the output, which reports things which don't exist in that scope at all...

import tbvaccine
tbvaccine.add_hook(isolate=False)

import dask
import dask.distributed


def x(arg1=123):
    assert arg1 == 122, "qwe"

if __name__ == '__main__':
    client = dask.distributed.Client()
    dask.delayed(x)().compute(get=client.get)
  File "/tmp/env/lib/python3.5/site-packages/dask/base.py", line 203, in compute
    results = get(dsk, keys, **kwargs)
|     x = b'\x80\x04\x95\xa1\x00\x00\x00\x00\x00\x00\x00\x8c\x16tblib.pickling_support\x94\x8c\x12unpickle_traceback\x94\x93\x94\x8c\x05tblib\x94\x8c\x05Frame\x94\x93\x94)\x81\x94}\x94(\x8c\x06f_code\x94h\x03\x8c\x04Code\x94\x93\x94)\x81\x94}\x94(\x8c\x07co_name\x94\x8c\x01x\x94\x8c\x0bco_filename\x94\x8c\x06qq4.py\x94ub\x8c\tf_globals\x94}\x94ubK\tN\x87\x94R\x94.'
  File "/tmp/env/lib/python3.5/site-packages/distributed/client.py", line 1590, in get
    resources=resources)
|     ret       = <tblib.Traceback object at 0x7f95aeadfcf8>
|     tb_frame  = <tblib.Frame object at 0x7f95aeadf908>
|     tb_lineno = 9
|     tb_next   = None
  File "/tmp/env/lib/python3.5/site-packages/distributed/utils.py", line 223, in sync
    six.reraise(*error[0])
|     code   = <code object x at 0x7f95aeb33270, file "qq4.py", line 9>
|     f_code = <tblib.Code object at 0x7f95aeadf9b0>
|     self   = <tblib.Traceback object at 0x7f95aeadfcf8>
|     tb     = <traceback object at 0x7f95aeaeb148>
  File "/tmp/env/lib/python3.5/site-packages/six.py", line 686, in reraise
    raise value
AssertionError: qwe

The direct call to x() produces a sane output, so it should be some magic involved with Dask. Better-Exceptions module just hangs in this situation, so TBVaccine is better in this respect, but it is still completely misleading and unhelpful.

Frames local variables

It would be amazing to see local variables in each frame of the traceback. It really helps debugging.

Support force-enable (even when not isatty)

Hi, thanks for creating this great library!

I want to use this library in a kubernetes container where stderr is not a tty.
It'll be convenient if we can do force-enabling by setting an environment variable.

ValueError: max() arg is an empty sequence

Executing:

def x():
    raise Exception('hello')

def a(b):
    b()

a(x)
d:\...>python -m tbvaccine test_stack_trace.py
Error in sys.excepthook:
Traceback (most recent call last):
  File "d:\...\tbvaccine\tbv.py", line 193, in print_exception
    formatted = self._format_tb_string_with_locals(etype, value, tb)
  File "d:\...\tbvaccine\tbv.py", line 173, in _format_tb_string_with_locals
    max_length = max([len(x[0]) for x in var_tuples])
ValueError: max() arg is an empty sequence

Original exception was:
Traceback (most recent call last):
  File "C:\...\lib\runpy.py", line 193, in _run_module_as_main
    "__main__", mod_spec)
  File "C:\...\lib\runpy.py", line 85, in _run_code
    exec(code, run_globals)
  File "d:\...\tbvaccine\__main__.py", line 67, in <module>
    exec(code, variables, variables)
  File "test_stack_trace.py", line 7, in <module>
    a(x)
  File "test_stack_trace.py", line 5, in a
    b()
  File "test_stack_trace.py", line 2, in x
    raise Exception('hello')
Exception: hello

Support for white background

The trace is basically unreadable when using a bright background for the terminal:
image

pls add support to an alternative color scheme...

Running tbvaccine on non python file - colors don't work

By mistake I just called python -m tbvaccine tox.ini.

The trace has no colors and it is longer then 100 lines, however calling python directly on a non python file causes only 4 lines for a single exception.

image

It would be great if tbvaccine could detect when a non python file is passed.

On Ubuntu 16.04, with Python 2.7, performance impact is non-trivial

Without adding hook to my module (tgv):

Traceback (most recent call last):
File "./tgv.py", line 618, in
if name == "main": tgv()
File "./tgv.py", line 426, in tgv
1/0
ZeroDivisionError: integer division or modulo by zero

real 0m2.904s
user 0m2.344s
sys 0m0.536s

With hook added

Traceback (most recent call last):
File "./tgv.py", line 618, in
if name == "main": tgv()
<6 variables printed>
File "./tgv.py", line 426, in tgv
1/0
<20 odd variables>
ZeroDivisionError: integer division or modulo by zero

real 0m30.856s
user 0m29.192s
sys 0m1.572s

I'm guessing mostly the perf degradation is due to the high count of variables being printed.
Anyway to control the output?

Looks like wrong coloring

On MacOS High Sierra, with system Python 2.7.10, tbvaccine 0.2.2 coloring does not look correct. At least not like your examples:
tbvaccine

How to integrate with flask or logging?

It no effect when exception raised in flask request because the tracebacks are formatted by logging, the sys.excepthook is not called.

eg:

import tbvaccine
from flask import Flask

tbvaccine.add_hook(isolate=True)
app = Flask(__name__)


@app.route('/')
def index():
    return 1 / 0


if __name__ == '__main__':
    app.run()

the outputs:

 * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
[2017-06-01 21:59:08,086] ERROR in app: Exception on / [GET]
Traceback (most recent call last):
  File "/home/guyskk/.local/share/virtualenvs/next_passport-OfYZSIo0/lib/python3.6/site-packages/flask/app.py", line 1982, in wsgi_app
    response = self.full_dispatch_request()
  File "/home/guyskk/.local/share/virtualenvs/next_passport-OfYZSIo0/lib/python3.6/site-packages/flask/app.py", line 1614, in full_dispatch_request
    rv = self.handle_user_exception(e)
  File "/home/guyskk/.local/share/virtualenvs/next_passport-OfYZSIo0/lib/python3.6/site-packages/flask/app.py", line 1517, in handle_user_exception
    reraise(exc_type, exc_value, tb)
  File "/home/guyskk/.local/share/virtualenvs/next_passport-OfYZSIo0/lib/python3.6/site-packages/flask/_compat.py", line 33, in reraise
    raise value
  File "/home/guyskk/.local/share/virtualenvs/next_passport-OfYZSIo0/lib/python3.6/site-packages/flask/app.py", line 1612, in full_dispatch_request
    rv = self.dispatch_request()
  File "/home/guyskk/.local/share/virtualenvs/next_passport-OfYZSIo0/lib/python3.6/site-packages/flask/app.py", line 1598, in dispatch_request
    return self.view_functions[rule.endpoint](**req.view_args)
  File "app.py", line 10, in index
    return 1 / 0
ZeroDivisionError: division by zero
127.0.0.1 - - [01/Jun/2017 21:59:08] "GET / HTTP/1.1" 500 -

Integration with IDEs

Hello there! Thank you very much for your work.

I'd like to get it to work in PyCharm, alas it's not trigerring at all there, but it works in consoles. Any advice here? :)

TBVaccine in pipe mode is broken

$ echo 1 | tbvaccine
Traceback (most recent call last):
  File "/mnt/storage/miniconda3/envs/CloudSML-Computational-Backend/bin/tbvaccine", line 11, in <module>
    sys.exit(main())
  File "/mnt/storage/miniconda3/envs/CloudSML-Computational-Backend/lib/python3.5/site-packages/tbvaccine/cli.py", line 29, in main
    output = tbv.process_line(line)
AttributeError: 'TBVaccine' object has no attribute 'process_line'

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.