Skip to main content

Hunter is a flexible code tracing toolkit, not for measuring coverage, but for debugging, logging, inspection and other nefarious purposes. It has a simple Python API and a convenient terminal API (see Environment variable activation).

  • Free software: BSD license

Installation

pip install hunter

Documentation

https://python-hunter.readthedocs.org/

Overview

The default action is to just print the code being executed. Example:

import hunter
hunter.trace(module='posixpath')

import os
os.path.join('a', 'b')

Would result in:

python2.7/posixpath.py:60    call      def join(a, *p):
python2.7/posixpath.py:64    line          path = a
python2.7/posixpath.py:65    line          for b in p:
python2.7/posixpath.py:66    line              if b.startswith('/'):
python2.7/posixpath.py:68    line              elif path == '' or path.endswith('/'):
python2.7/posixpath.py:71    line                  path += '/' + b
python2.7/posixpath.py:65    line          for b in p:
python2.7/posixpath.py:72    line          return path
python2.7/posixpath.py:72    return        return path
                             ...       return value: 'a/b'
  • or in a terminal:

https://raw.githubusercontent.com/ionelmc/python-hunter/master/docs/simple-trace.png

You can have custom actions, like a variable printer - example:

import hunter
hunter.trace(hunter.Q(module='posixpath', action=hunter.VarsPrinter('path')))

import os
os.path.join('a', 'b')

Would result in:

python2.7/posixpath.py:60    call      def join(a, *p):
python2.7/posixpath.py:64    line          path = a
                             vars      path => 'a'
python2.7/posixpath.py:65    line          for b in p:
                             vars      path => 'a'
python2.7/posixpath.py:66    line              if b.startswith('/'):
                             vars      path => 'a'
python2.7/posixpath.py:68    line              elif path == '' or path.endswith('/'):
                             vars      path => 'a'
python2.7/posixpath.py:71    line                  path += '/' + b
                             vars      path => 'a/b'
python2.7/posixpath.py:65    line          for b in p:
                             vars      path => 'a/b'
python2.7/posixpath.py:72    line          return path
                             vars      path => 'a/b'
python2.7/posixpath.py:72    return        return path
                             ...       return value: 'a/b'
  • or in a terminal:

https://raw.githubusercontent.com/ionelmc/python-hunter/master/docs/vars-trace.png

You can give it a tree-like configuration where you can optionally configure specific actions for parts of the tree (like dumping variables or a pdb set_trace):

TODO: More examples.

Environment variable activation

For your convenience environment variable activation is available. Just run your app like this:

PYTHONHUNTER="module='os.path'" python yourapp.py

On Windows you’d do something like:

set PYTHONHUNTER=module='os.path'
python yourapp.py

The activation works with a clever .pth file that checks for that env var presence and before your app runs does something like this:

from hunter import *
trace(<whatever-you-had-in-the-PYTHONHUNTER-env-var>)

Note that Hunter is activated even if the env var is empty, eg: PYTHONHUNTER="".

Filtering DSL

Hunter supports a flexible query DSL, see the introduction.

Development

To run the all tests run:

tox

FAQ

Why not Smiley?

There’s some obvious overlap with smiley but there are few fundamental differences:

  • Complexity. Smiley is simply over-engineered:

    • It’s uses IPC and a SQL database.

    • It has a webserver. Lots of dependencies.

    • It uses threads. Side-effects and subtle bugs are introduced in your code.

    • It records everything. Tries to dump any variable. Often fails and stops working.

    Why do you need all that just to debug some stuff in a terminal? Simply put, it’s a nice idea but the design choices work against you when you’re already neck-deep into debugging your own code. In my experience Smiley has been very buggy and unreliable. Your mileage might way of course.

  • Tracing long running code. This will make Smiley record lots of data, making it unusable.

    Now because Smiley records everything, you’d think it’s better suited for short programs. But alas, if your program runs quickly then it’s pointless to record the execution. You can just run it again.

    It seems there’s only one situation where it’s reasonable to use Smiley: tracing io-bound apps remotely. Those apps don’t execute lots of code, they just wait on network so Smiley’s storage won’t blow out of proportion and tracing overhead might be acceptable.

  • Use-cases. It seems to me Smiley’s purpose is not really debugging code, but more of a “non interactive monitoring” tool.

In contrast, Hunter is very simple:

  • Few dependencies.

  • Low overhead (tracing/filtering code has an optional Cython extension).

  • No storage. This simplifies lots of things.

    The only cost is that you might need to run the code multiple times to get the filtering/actions right. This means Hunter is not really suited for “post-mortem” debugging. If you can’t reproduce the problem anymore then Hunter won’t be of much help.

Why (not) coverage?

For purposes of debugging coverage is a great tool but only as far as “debugging by looking at what code is (not) run”. Checking branch coverage is good but it will only get you as far.

>From the other perspective, you’d be wondering if you could use Hunter to measure coverage-like things. You could do it but for that purpose Hunter is very “rough”: it has no builtin storage. You’d have to implement your own storage. You can do it but it wouldn’t give you any advantage over making your own tracer if you don’t need to “pre-filter” whatever you’re recording.

In other words, filtering events is the main selling point of Hunter - it’s fast (cython implementation) and the query API is flexible enough.

Changelog

1.1.0 (2016-01-21)

  • Implemented a destructor (__dealloc__) for the Cython tracer.

  • Improved the restoring of the previous tracer in the Cython tracer (use PyEval_SetTrace) directly.

  • Removed tracer as an allowed filtering argument in hunter.Query.

  • Add basic validation (must be callable) for positional arguments and actions passed into hunter.Q. Closes #23.

  • Fixed stdlib checks (wasn’t very reliable). Closes #24.

1.0.2 (2016-01-05)

  • Fixed missing import in setup.py.

1.0.1 (2015-12-24)

  • Fix a compile issue with the MSVC compiler (seems it don’t like the inline option on the fast_When_call).

1.0.0 (2015-12-24)

  • Implemented fast tracer and query objects in Cython. MAY BE BACKWARDS INCOMPATIBLE

    To force using the old pure-python implementation set the PUREPYTHONHUNTER environment variable to non-empty value.

  • Added filtering operators: contains, startswith, endswith and in. Examples:

    • Q(module_startswith='foo' will match events from foo, foo.bar and foobar.

    • Q(module_startswith=['foo', 'bar'] will match events from foo, foo.bar, foobar, bar, bar.foo and baroo .

    • Q(module_endswith='bar' will match events from foo.bar and foobar.

    • Q(module_contains='ip' will match events from lipsum.

    • Q(module_in=['foo', 'bar'] will match events from foo and bar.

    • Q(module_regex=r"(re|sre.*)\b") will match events from ``re, re.foobar, srefoobar but not from repr.

  • Removed the merge option. Now when you call hunter.trace(...) multiple times only the last one is active. BACKWARDS INCOMPATIBLE

  • Remove the previous_tracer handling. Now when you call hunter.trace(...) the previous tracer (whatever was in sys.gettrace()) is disabled and restored when hunter.stop() is called. BACKWARDS INCOMPATIBLE

  • Fixed CodePrinter to show module name if it fails to get any sources.

0.6.0 (2015-10-10)

  • Added a clear_env_var option on the tracer (disables tracing in subprocess).

  • Added force_colors option on VarsPrinter and CodePrinter.

  • Allowed setting the stream to a file name (option on VarsPrinter and CodePrinter).

  • Bumped up the filename alignment to 40 cols.

  • If not merging then self is not kept as a previous tracer anymore. Closes #16.

  • Fixed handling in VarsPrinter: properly print eval errors and don’t try to show anything if there’s an AttributeError. Closes #18.

  • Added a stdlib boolean flag (for filtering purposes). Closes #15.

  • Fixed broken frames that have “None” for filename or module (so they can still be treated as strings).

  • Corrected output files in the install_lib command so that pip can uninstall the pth file. This only works when it’s installed with pip (sadly, setup.py install/develop and pip install -e will still leave pth garbage on pip uninstall hunter).

0.5.1 (2015-04-15)

  • Fixed Event.globals to actually be the dict of global vars (it was just the locals).

0.5.0 (2015-04-06)

  • Fixed And and Or “single argument unwrapping”.

  • Implemented predicate compression. Example: Or(Or(a, b), c) is converted to Or(a, b, c).

  • Renamed the Event.source to Event.fullsource.

  • Added Event.source that doesn’t do any fancy sourcecode tokenization.

  • Fixed Event.fullsource return value for situations where the tokenizer would fail.

  • Made the print function available in the PYTHONHUNTER env var payload.

  • Added a __repr__ for Event.

0.4.0 (2015-03-29)

  • Disabled colors for Jython (contributed by Claudiu Popa in #12).

  • Test suite fixes for Windows (contributed by Claudiu Popa in #11).

  • Added an introduction section in the docs.

  • Implemented a prettier fallback for when no sources are available for that frame.

  • Implemented fixups in cases where you use action classes as a predicates.

0.3.1 (2015-03-29)

  • Forgot to merge some commits …

0.3.0 (2015-03-29)

  • Added handling for internal repr failures.

  • Fixed issues with displaying code that has non-ascii characters.

  • Implemented better display for call frames so that when a function has decorators the function definition is shown (instead of just the first decorator). See: #8.

0.2.1 (2015-03-28)

  • Added missing color entry for exception events.

  • Added Event.line property. It returns the source code for the line being run.

0.2.0 (2015-03-27)

  • Added color support (and colorama as dependency).

  • Added support for expressions in VarsPrinter.

  • Breaking changes:

    • Renamed F to Q. And Q is now just a convenience wrapper for Query.

    • Renamed the PYTHON_HUNTER env variable to PYTHONHUNTER.

    • Changed When to take positional arguments.

    • Changed output to show 2 path components (still not configurable).

    • Changed VarsPrinter to take positional arguments for the names.

  • Improved error reporting for env variable activation (PYTHONHUNTER).

  • Fixed env var activator (the .pth file) installation with setup.py install (the “egg installs”) and setup.py develop/pip install -e (the “egg links”).

0.1.0 (2015-03-22)

  • First release on PyPI.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

hunter-1.1.0.tar.gz (191.7 kB view details)

Uploaded Source

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

hunter-1.1.0-cp35-none-win_amd64.whl (257.8 kB view details)

Uploaded CPython 3.5Windows x86-64

hunter-1.1.0-cp35-none-win32.whl (246.1 kB view details)

Uploaded CPython 3.5Windows x86

hunter-1.1.0-cp34-none-win_amd64.whl (252.2 kB view details)

Uploaded CPython 3.4Windows x86-64

hunter-1.1.0-cp34-none-win32.whl (243.8 kB view details)

Uploaded CPython 3.4Windows x86

hunter-1.1.0-cp27-none-win_amd64.whl (253.9 kB view details)

Uploaded CPython 2.7Windows x86-64

hunter-1.1.0-cp27-none-win32.whl (243.2 kB view details)

Uploaded CPython 2.7Windows x86

File details

Details for the file hunter-1.1.0.tar.gz.

File metadata

  • Download URL: hunter-1.1.0.tar.gz
  • Upload date:
  • Size: 191.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No

File hashes

Hashes for hunter-1.1.0.tar.gz
Algorithm Hash digest
SHA256 33cbdf8043717d93577755c4c2042e1f16173543a45ac1e524d7bd05deb16e51
MD5 8b7d70fbdb18289378ce1c40a2000b1d
BLAKE2b-256 fb6a4366af8b25406b1de8bf1bf52a1270ed6fe37d711bfcbdb457e8a56fb2ad

See more details on using hashes here.

File details

Details for the file hunter-1.1.0-cp35-none-win_amd64.whl.

File metadata

File hashes

Hashes for hunter-1.1.0-cp35-none-win_amd64.whl
Algorithm Hash digest
SHA256 02bd6b1d0975f3620b57f9af901f8c6113ad22ca3e6b8ef8ec785263991cafb8
MD5 b31c5790b5401b2c77d79438119d4757
BLAKE2b-256 63cdcaa05f698f5f29d2adab95d5ac3b508c7b01bf1a95a7a3bd418ef6684a02

See more details on using hashes here.

File details

Details for the file hunter-1.1.0-cp35-none-win32.whl.

File metadata

File hashes

Hashes for hunter-1.1.0-cp35-none-win32.whl
Algorithm Hash digest
SHA256 c6ff9898a9e654aa98d164d59d5aad7e5b5c2d0b32d947a88dc627fd5692605e
MD5 41d0d4438bc3e02fbe7cc9ff598ad115
BLAKE2b-256 6569429d2de0ae52b525b9ba3efa92374781450a7b0aad2a31cc813264d3b3fc

See more details on using hashes here.

File details

Details for the file hunter-1.1.0-cp34-none-win_amd64.whl.

File metadata

File hashes

Hashes for hunter-1.1.0-cp34-none-win_amd64.whl
Algorithm Hash digest
SHA256 a29e988be248c117401f4a7744510b777dbb508cc0db9d595335cf9cede6c16c
MD5 aba3feaafc6a5e1921011f168a580a6c
BLAKE2b-256 13bb6e8776a917b1f8824a4e7ae1e3bc318b099ff51621303ae3957df3d7bb9d

See more details on using hashes here.

File details

Details for the file hunter-1.1.0-cp34-none-win32.whl.

File metadata

File hashes

Hashes for hunter-1.1.0-cp34-none-win32.whl
Algorithm Hash digest
SHA256 28a0c66147d9472a2f59b49eeb2bb0b47f898ea09a25640036ec5eb63d74c78a
MD5 51b3ba085623320e392bea364fbc01cb
BLAKE2b-256 90f3b0bc737141d83297a9acbc59d193ea8436aeab345a8179a83d8cfc2c59e2

See more details on using hashes here.

File details

Details for the file hunter-1.1.0-cp27-none-win_amd64.whl.

File metadata

File hashes

Hashes for hunter-1.1.0-cp27-none-win_amd64.whl
Algorithm Hash digest
SHA256 5fb870249d7a6dda7653483c10c31cc4d5ab74aeb2f8c999c47408961c7f2cc4
MD5 a5f656347721d8b794da7bb5105cafc1
BLAKE2b-256 66a01b26c5efa2b83edcc02fca41c30d932798f34280d975939b3f1998e9ab1f

See more details on using hashes here.

File details

Details for the file hunter-1.1.0-cp27-none-win32.whl.

File metadata

File hashes

Hashes for hunter-1.1.0-cp27-none-win32.whl
Algorithm Hash digest
SHA256 e2ea5825e75d59825973adc5b3e11ba826ad93b4a92d0fcfff61263c5c3bd1bf
MD5 b87a6d68b93f764468995f746d0068aa
BLAKE2b-256 a1510d222e6eb595c619bc95a08d5270ad41932072353ba3660ce18d38667069

See more details on using hashes here.

Release history Release notifications | RSS feed

3.9.0

51 files

3.8.0

30 files

3.7.0

37 files

3.6.1

16 files

3.6.0

16 files

3.5.1

32 files

3.5.0

32 files

3.4.3

37 files

3.4.1

32 files

3.4.0

31 files

3.3.8

22 files

3.3.5

22 files

3.3.3

22 files

3.3.2

22 files

3.3.1

22 files

3.3.0

20 files

3.2.2

22 files

3.2.1

22 files

3.2.0

22 files

3.1.3

18 files

3.1.2

18 files

3.1.1

13 files

3.1.0

13 files

3.0.5

18 files

3.0.4

18 files

3.0.3

15 files

3.0.2

14 files

3.0.1

15 files

3.0.0

15 files

2.2.1

18 files

2.2.0.post1

1 file

2.2.0

18 files

2.1.0

22 files

2.0.2

23 files

2.0.1

23 files

2.0.0

23 files

1.4.1

14 files

1.4.0

8 files

1.3.0

14 files

1.2.2

7 files

1.2.1

7 files

1.2.0

7 files

This release

1.1.0 This release

7 files

1.0.2

7 files

1.0.1

7 files

1.0.0

1 file

0.6.0

2 files

0.5.1

2 files

0.5.0

2 files

0.4.0

2 files

0.3.1

2 files

0.3.0

2 files

0.2.1

2 files

0.2.0

2 files

0.1.0

2 files

0.0.1

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page