A powerful set of Python debugging tools, based on PySnooper

Overview

snoop

Build Status Supports Python versions 2.7 and 3.4+, including PyPy

snoop is a powerful set of Python debugging tools. It's primarily meant to be a more featureful and refined version of PySnooper. It also includes its own version of icecream and some other nifty stuff.

You're trying to figure out why your Python code isn't doing what you think it should be doing. You'd love to use a full-fledged debugger with breakpoints and watches, but you can't be bothered to set one up right now.

You want to know which lines are running and which aren't, and what the values of the local variables are.

Most people would use print lines, in strategic locations, some of them showing the values of variables.

snoop lets you do the same, except instead of carefully crafting the right print lines, you just add one decorator line to the function you're interested in. You'll get a play-by-play log of your function, including which lines ran and when, and exactly when local variables were changed.

Installation is as simple as pip install snoop.

Basic snoop usage

We're writing a function that converts a number to binary, by returning a list of bits. Let's snoop on it by adding the @snoop decorator:

import snoop

@snoop
def number_to_bits(number):
    if number:
        bits = []
        while number:
            number, remainder = divmod(number, 2)
            bits.insert(0, remainder)
        return bits
    else:
        return [0]

number_to_bits(6)

Note how easy it is: Just import snoop and @snoop. If you don't like the magical import, snoop.snoop and from snoop import snoop still work too. Or if you don't want to import in your project at all, just call install() somewhere once.

The output to stderr looks like this:

number_to_bits output

Let's try a more complex example. We're writing a memoizing decorator: it stores function arguments and return values in a cache to avoid recomputation:

import snoop

def cache(func):
    d = {}

    def wrapper(*args):
        try:
            return d[args]
        except KeyError:
            result = d[args] = func(*args)
            return result

    return wrapper

@snoop(depth=2)
@cache
def add(x, y):
    return x + y

add(1, 2)
add(1, 2)

Here we specify depth=2 to mean we should also step one level down into inner function calls. We then call the function twice to see the caching in action. Here's the output:

cache output

At a glance we can see that in the first call the cache lookup failed with a KeyError so the original add function was called, while in the second call the previously cached result was returned immediately.

If you don't want to trace an entire function, you can wrap the relevant part in a with block:

import snoop
import random

def foo():
    lst = []
    for i in range(10):
        lst.append(random.randrange(1, 1000))

    with snoop:
        lower = min(lst)
        upper = max(lst)
        mid = (lower + upper) / 2

    return lower, mid, upper

foo()

which outputs something like:

foo output

Common arguments

  • depth: as seen above, snoops deeper calls made by the function/block you trace. The default is 1, meaning no inner calls, so pass something bigger.
  • watch: show values of arbitrary expressions by specifying them as a string, e.g:
@snoop(watch=('foo.bar', 'self.x["whatever"]'))
  • watch_explode: Expand variables or expressions to see all their attributes or items of lists/dictionaries:
@snoop(watch_explode=['foo', 'self'])

This will output lines like:

........ foo[2] = 'whatever'
........ self.baz = 8

See Controlling watch_explode for more advanced usage of this argument.

See watch_extras to show additional information about any value (local variable, watched expression, or exploded item) automatically.

pp - awesome print debugging

While snoop is meant to save you from writing print calls, sometimes that's still exactly the kind of thing you need. pp aims to be the best possible version of this. It can be used alone or in combination with snoop.

pp(x) will output x = <pretty printed value of x>, i.e. it will show the source code of its argument(s) so you know what's being printed, and format the value with pprint.pformat so that you can easily see the layout of complicated data structures.

pp will return its argument directly so you can easily insert it in code without rearranging. If given multiple arguments, it will return them as a tuple, so you can replace foo(x, y) with foo(*pp(x, y)) to leave the behaviour of the code intact.

Here's an example:

from snoop import pp
x = 1
y = 2
pp(pp(x + 1) + max(*pp(y + 2, y + 3)))

Output:

12:34:56.78 LOG:
12:34:56.78 .... x + 1 = 2
12:34:56.78 LOG:
12:34:56.78 .... y + 2 = 4
12:34:56.78 .... y + 3 = 5
12:34:56.78 LOG:
12:34:56.78 .... pp(x + 1) + max(*pp(y + 2, y + 3)) = 7

If you've already got import snoop you can also use snoop.pp. But ideally, you would use install() to avoid importing at all.

There are a few situations where pp can't find the source code of its arguments, in which case it will show a placeholder instead:

  • When the source file cannot be found, usually because it doesn't exist, e.g. if you're in a Python shell. The source is fetched from linecache.
  • In Python 3.4 and PyPy.
  • In the presence of magic which transforms source code under the hood, such as pytest or birdseye (and thus the @spy decorator).
  • When the source file has been modified before the first call to pp or snoop.

Under the hood, pp uses the library executing to locate the AST node of the function call - check it out if you'd like to write some cool utilities of your own.

pp is inspired by icecream and offers the same basic API for printing, but pp integrates seamlessly with snoop and offers pp.deep, which is unique.

'pp' stands for 'pretty-print' and totally definitely absolutely has no other meaning. It's also very easy and quick to type.

pp.deep for tracing subexpressions

If you have pp(<complicated expression>) and you want to see what happens inside that expression and not just the final value, replace it wth pp.deep(lambda: <complicated expression>). This will log every intermediate subexpression, in the correct order, with no additional side effects, and return the final value. Repeating the previous example:

pp.deep(lambda: x + 1 + max(y + 2, y + 3))

Output:

12:34:56.78 LOG:
12:34:56.78 ............ x = 1
12:34:56.78 ........ x + 1 = 2
12:34:56.78 ................ y = 2
12:34:56.78 ............ y + 2 = 4
12:34:56.78 ................ y = 2
12:34:56.78 ............ y + 3 = 5
12:34:56.78 ........ max(y + 2, y + 3) = 5
12:34:56.78 .... x + 1 + max(y + 2, y + 3) = 7

(the values of literals and builtins are left out because they're trivial)

If an exception is raised, it'll show which subexpression is responsible, which looks something like this:

12:34:56.78 ................ y = 2
12:34:56.78 ............ y + 3 = 5
12:34:56.78 ........ (y + 3) / 0 = !!! ZeroDivisionError!
12:34:56.78 !!! ZeroDivisionError: division by zero

If you like this, you'll probably love @spy.

@spy

The @spy decorator lets you combine @snoop with the powerful debugger birdseye. The code:

from snoop import spy  # not required if you use install()

@spy
def foo():

is roughly equivalent to:

import snoop
from birdseye import eye

@snoop
@eye
def foo():

To reduce the dependencies of snoop, you'll need to install birdseye separately: pip install birdseye.

The only big disadvantage of @spy is that it significantly reduces performance, so avoid it for functions with many loop iterations. Otherwise you can basically always use it instead of @snoop. Then if the logs don't have the information you need you can open up the birdseye UI to see more detail, without needing to edit or rerun your code. Great for when you're feeling lazy and unsure which tool is best.

spy passes its arguments to snoop, so e.g. @spy(depth=2, watch='x.y') works.

Read more about birdseye in the documentation here.

('spy' is so named because it's a combination of the decorator names 'snoop' and 'eye')

install()

To make regularly debugging your project more convenient, run this code early on:

import snoop

snoop.install()

Then snoop, pp, and spy will be available in every file without needing to import them.

You can choose different names by passing keyword arguments <original name>=<new name>, e.g:

snoop.install(snoop="ss")

will let you decorate functions with @ss.

If you dislike this feature and would prefer to just import normally, but you want to use install() for other configuration, pass builtins=False.

As an alternative, in Python 3.7+ you can use the new breakpoint function in place of snoop if you set the environment variable PYTHONBREAKPOINT=snoop.snoop.

Disabling

If you would like to leave snoop and other functions in your codebase but disable their effects, pass enabled=False. For example, if you're using Django, put snoop.install(enabled=DEBUG) in settings.py to automatically disable it in production. When disabled, performance impact is minimised and there is no output anywhere.

You can also dynamically re-enable the functions at any point by calling snoop.install(enabled=True) again, e.g. in a special view or signal handler.

Output configuration

install has several keyword arguments for controlling the output of snoop and pp:

  • out: determines the output destination. By default this is stderr. You can also pass:

    • A string or a Path object to write to a file at that location. By default this always will append to the file. Pass overwrite=True to clear the file initially.
    • Anything with a write method, e.g. sys.stdout or a file object.
    • Any callable with a single string argument, e.g. logger.info.
  • color: determines whether the output includes escape characters to display colored text in the console. If you see weird characters in your output, your console doesn't support colors, so pass color=False.

    • Code is syntax highlighted using Pygments, and this argument is passed as the style. You can choose a different color scheme by passing a string naming a style (see this gallery) or a style class. The default style is monokai.
    • By default this parameter is set to out.isatty(), which is usually true for stdout and stderr but will be false if they are redirected or piped. Pass True or a style if you want to force coloring.
    • To see colors in the PyCharm Run window, edit the Run Configuration and tick "Emulate terminal in output console".
  • prefix: Pass a string to start all snoop lines with that string so you can grep for them easily.

  • columns: This specifies the columns at the start of each output line. You can pass a string with the names of built in columns separated by spaces or commas. These are the available columns:

    • time: The current time. This is the only column by default.
    • thread: The name of the current thread.
    • thread_ident: The identifier of the current thread, in case thread names are not unique.
    • file: The filename (not the full path) of the current function.
    • full_file: The full path to the file (also shown anyway when the function is called).
    • function: The name of the current function.
    • function_qualname: The qualified name of the current function.
  • watch_extras and replace_watch_extras: read about these under Advanced usage

    If you want a custom column, please open an issue to tell me what you're interested in! In the meantime, you can pass a list, where the elements are either strings or callables. The callables should take one argument, which will be an Event object. It has attributes frame, event, and arg, as specified in sys.settrace(), and other attributes which may change.

API differences from PySnooper

If you're familiar with PySnooper and want to use snoop, there are a few things you should be aware of that you have to do differently:

  • Pass prefix and overwrite to install(), not snoop().
  • The first argument to pysnooper.snoop, called output, should be passed to install with the keyword out.
  • Instead of snoop(thread_info=True), write install(columns='time thread thread_ident').
  • Instead of the environment variable PYSNOOPER_DISABLED, use install(enabled=False).
  • Instead of using custom_repr, see watch_extras and Customising the display of variables.

If you're not sure if it's worth using snoop instead of PySnooper, read the comparison here.

IPython/Jupyter integration

snoop comes with an IPython extension that you can use in shells or notebooks.

First you need to load the extension, using either %load_ext snoop in a notebook cell or by adding 'snoop' to the list c.InteractiveShellApp.extensions in your IPython configuration file, e.g. ~/.ipython/profile_default/ipython_config.py.

Then use the cell magic %%snoop at the top of a notebook cell to trace that cell:

%%snoop example

Advanced usage

watch_extras

install has another parameter called watch_extras. You can pass it a list of functions to automatically show extra information about any value: local variables, watched expressions, and exploded items. For example, suppose you wanted to see the type of every variable. You could define a function like this:

def type_watch(source, value):
    return 'type({})'.format(source), type(value)

You would then write install(watch_extras=[type_watch]). The result is output like this:

12:34:56.78    9 |     x = 1
12:34:56.78 .......... type(x) = <class 'int'>
12:34:56.78   10 |     y = [x]
12:34:56.78 .......... y = [1]
12:34:56.78 .......... type(y) = <class 'list'>

The functions you write should accept two arguments source and value - typically these will be the name of a variable and its actual value. They should return a pair representing the 'source' of the returned information (used only for display, it doesn't have to be valid Python) and the actual information. If you don't want to display anything for this particular value, return None. Any exceptions raised are caught and silenced.

Two such functions are already enabled by default: one which shows either the len() or the .shape property (used by numpy, pandas, tensorflow, etc) of values, and one which shows the .dtype property.

watch_extras is added to these two default functions so you don't have to specify them again. If you don't want to include them, use replace_watch_extras instead to specify the exact list. The original functions can be found here:

from snoop.configuration import len_shape_watch, dtype_watch

Controlling watch_explode

watch_explode will automatically guess how to expand the expression passed to it based on its class. You can be more specific by using one of the following classes:

@snoop(watch=(
    snoop.Attrs('x'),    # Attributes (specifically from __dict__ or __slots__)
    snoop.Keys('y'),     # Mapping (e.g. dict) items, based on .keys()
    snoop.Indices('z'),  # Sequence (e.g. list/tuple) items, based on len()
))

Exclude specific keys/attributes/indices with the exclude parameter, e.g. Attrs('x', exclude=('_foo', '_bar')).

Add a slice after Indices to only see the values within that slice, e.g. Indices('z')[-3:].

Customising the display of variables

(See also watch_extras)

Values are rendered using the cheap_repr library to improve performance and avoid flooding the console. It has a specially defined repr function for most common classes, including from third party libraries. If a class is missing, please open an issue there. You can also register your own repr for the class. Here's an example:

from cheap_repr import register_repr, cheap_repr

@register_repr(MyClass)
def repr_my_class(x, helper):
    return '{}(items={})'.format(
        x.__class__.__name__, 
        cheap_repr(x.items, helper.level - 1),
    )

Read more here.

You can also increase the verbosity of individual classes (see the documentation), e.g:

from cheap_repr import find_repr_function

find_repr_function(list).maxparts = 100

Multiple separate configurations

If you need more control than the global install function, e.g. if you want to write to several different files in one process, you can create a Config object, e.g: config = snoop.Config(out=filename). Then config.snoop, config.pp and config.spy will use that configuration rather than the global one.

The arguments are the same as the arguments of install() relating to output configuration and enabled.

Contribute

Feedback and discussions

I'd love to hear from users! Obviously open an issue if you have one, but also check out the issues with the 'discussion' label. There's still a lot more work that can be done and I really want people's opinions so that I can do it right.

You can also email me what you like or hate about snoop. Just knowing it's being used is helpful.

Developing

Pull requests are always welcome!

Please, write tests and run them with Tox.

Tox installs all dependencies automatically. You only need to install Tox itself:

$ pip install tox

If you want to run tests against all target Python versions use pyenv to install them. Otherwise, you can run only the ones you have already installed on your machine:

# run only some interpreters
$ tox -e py27,py36

Or just install project in developer mode with test dependencies:

$ pip install -e path/to/snoop[tests]

And run tests:

$ pytest
Comments
  • Add pformat to config object

    Add pformat to config object

    I sometimes find pprint.pformat suboptimal so it would be nice if I could drop-in replace it for snoop. This PR adds pp_pformat to the config object (and the snoop.install method) to override it with some other function.

    It is also useful if you want to configure pprint.pformat, for example passing sort_keys=False.

    opened by danr 20
  • some small tidyups

    some small tidyups

    was just running pylint runner

    • cleaned up white space
    • tidied imports with isort
    • ensured tests still pass

    There's a lot more that can be done once 2.7 stops getting supported.

    opened by marksmayo 9
  • Enable snoop during a recursive trace

    Enable snoop during a recursive trace

    Hi,

    I'm working on a debugging toolbox which includes snoop (as well as Birdseye). One of the features is to automatically wrap a function that raises while tracing and, since there's no way to move execution back to the point before the function was run (without maybe some arcade bytecode hacking), eval the wrapped function again during the handling of the exception. One of the things that wrapper does is wrap the function with spy before running it again. I find that Birdseye works fine, however snoop provides no feedback. Is this the intended behavior? How can I work around it?

    opened by skeledrew 7
  • Somehow wrapping my pytorch tensor in pp breaks it when training on gpu

    Somehow wrapping my pytorch tensor in pp breaks it when training on gpu

    I added one line similar to this: pp(my_tensor) to view the contents of my pytorch tensor when on gpu but it returns the following error:

    terminate called after throwing an instance of 'c10::Error'
      what():  CUDA error: initialization error
    Exception raised from insert_events at /opt/conda/conda-bld/pytorch_1607369981906/work/c10/cuda/CUDACachingAllocator.cpp:717 (most recent call first):
    frame #0: c10::Error::Error(c10::SourceLocation, std::string) + 0x42 (0x7f11b91498b2 in /home/nxingyu2/miniconda3/envs/NLP/lib/python3.8/site-packages/torch/lib/libc10.so)
    frame #1: c10::cuda::CUDACachingAllocator::raw_delete(void*) + 0x1070 (0x7f11b939bf20 in /home/nxingyu2/miniconda3/envs/NLP/lib/python3.8/site-packages/torch/lib/libc10_cuda.so)
    frame #2: c10::TensorImpl::release_resources() + 0x4d (0x7f11b9134b7d in /home/nxingyu2/miniconda3/envs/NLP/lib/python3.8/site-packages/torch/lib/libc10.so)
    frame #3: <unknown function> + 0x5f9e52 (0x7f11fa901e52 in /home/nxingyu2/miniconda3/envs/NLP/lib/python3.8/site-packages/torch/lib/libtorch_python.so)
    <omitting python frames>
    

    Not sure if this is something to post here, but would like to raise it in case anyone else face a similar issue

    opened by ngxingyu 6
  • module not found

    module not found

    created a virtual environment.

    /Users/soft_orca/.leetcode/venv/bin/python3.8 -m pip install snoop

    import snoop at top of file

    run code -> get error. ImportError: No module named snoop

    opened by nitgo-latte 5
  • Output buffering is altered

    Output buffering is altered

    When using the snoop decorator in docker compose, all my output appears to be buffered, meaning there are significant delays in when the log output is shown.

    It is not only the snoop output which is affected, but also normal logging statements. It affects buffering in the entire python application, not just the decorated functions.

    If the package is installed, but nothing is decorated, there is no adverse effect.

    opened by nicois 5
  • Stale output when python file changes during runtime

    Stale output when python file changes during runtime

    I'm writing a live-reloading library on top of python which compiles and executes the same file each time it is saved. When running snoop inside such a file we see that snoop keeps referring to the first saved version of the file even when it has been changed. I'm attaching code that reproduces this:

    Setup

    open('./live.py', 'w').write('''
    import snoop
    with snoop:
        x = 1
        y = 2
        print(x, y)
    ''')
    
    exec(compile(open('./live.py').read(), 'live.py', 'exec'), {})
    
    open('./live.py', 'w').write('''
    import snoop
    with snoop:
        x = 4
        y = 5
        print(x, y)
    ''')
    
    exec(compile(open('./live.py').read(), 'live.py', 'exec'), {})
    

    Observed output

    17:10:01.04 >>> Enter with block in <module> in File "live.py", line 3
    17:10:01.04 ...... __builtins__ = {'__name__': 'builtins', '__doc__': "Built-in functions, exceptions, and other object...nil' object; Ellipsis represents `...' in slices.", '__package__': '', '__loader__': <class '_frozen_importlib.BuiltinImporter'>, ...}
    17:10:01.04 ...... len(__builtins__) = 152
    17:10:01.04 ...... snoop = <class 'snoop.configuration.Config.__init__.<locals>.ConfiguredTracer'>
    17:10:01.04    4 |     x = 1
    17:10:01.04    5 |     y = 2
    17:10:01.04    6 |     print(x, y)
    1 2
    17:10:01.04 <<< Exit with block in <module>
    17:10:01.04 >>> Enter with block in <module> in File "live.py", line 3
    17:10:01.04 ...... __builtins__ = {'__name__': 'builtins', '__doc__': "Built-in functions, exceptions, and other object...nil' object; Ellipsis represents `...' in slices.", '__package__': '', '__loader__': <class '_frozen_importlib.BuiltinImporter'>, ...}
    17:10:01.04 ...... len(__builtins__) = 152
    17:10:01.04 ...... snoop = <class 'snoop.configuration.Config.__init__.<locals>.ConfiguredTracer'>
    17:10:01.04    4 |     x = 1
    17:10:01.04 .......... x = 4
    17:10:01.04    5 |     y = 2
    17:10:01.04 .......... y = 5
    17:10:01.04    6 |     print(x, y)
    4 5
    17:10:01.04 <<< Exit with block in <module>
    

    Expected output

    # ... same as above until:
    17:10:01.04    4 |     x = 4
    17:10:01.04 .......... x = 4
    17:10:01.04    5 |     y = 5
    17:10:01.04 .......... y = 5
    17:10:01.04    6 |     print(x, y)
    4 5
    17:10:01.04 <<< Exit with block in <module>
    
    opened by danr 4
  • multiple snoop configs display weirdly

    multiple snoop configs display weirdly

    Defining multiple snoops cause the console output stderr to dispaly two extra snoop outputs which are "Call to Tracer.call." and Return value from Tracer.call. which also contain extra long ".............." lines

    snoop.install()
    config = snoop.Config()
    
    @snoop
    @config.snoop
    def get_repo_tree(user, repo, branch, logged_in_user=None):
      blah
    

    I would expect two normal snoop outputs, instead I get one normal output wrapped in these tracer calls:

    09:44:51.06 >>> Call to Tracer.__call__.<locals>.simple_wrapper in File "/Users/andy/.local/share/virtualenvs/gituml-Iv6Hkut1/lib/python3.6/site-packages/snoop/tracer.py", line 167
    09:44:51.06 .............. args = ('matplotlib', 'matplotlib', '99d8900eacaad01b1ff6e5d482e4e17683dd36be')
    09:44:51.06 .............. len(args) = 3
    09:44:51.06 .............. kwargs = {'logged_in_user': <SimpleLazyObject: <User: andy22>>}
    09:44:51.06 .............. len(kwargs) = 1
    09:44:51.06 .............. function = <function get_repo_tree at 0x10d71b730>
    09:44:51.06 .............. self = <snoop.configuration.Config.__init__.<locals>.ConfiguredTracer object at 0x10d6d8198>
    09:44:51.06  167 |         def simple_wrapper(*args, **kwargs):
    09:44:51.07  168 |             with self:
    09:44:51.07  169 |                 return function(*args, **kwargs)
    
    09:44:51.07 >>> Call to get_repo_tree in File "/Users/Andy/Devel/gituml/lib/repo/repo_tree.py", line 58
    09:44:51.07 ...... user = 'matplotlib'
    09:44:51.07 ...... repo = 'matplotlib'
    09:44:51.07 ...... branch = '99d8900eacaad01b1ff6e5d482e4e17683dd36be'
    09:44:51.07 ...... logged_in_user = <SimpleLazyObject: <User: andy22>>
    09:44:51.07   58 | def get_repo_tree(user, repo, branch, logged_in_user=None):
    09:44:51.07   73 |     if is_sha(branch):
    09:44:51.07   74 |         return get_repo_tree_sha(user, repo, branch)
    https://api.github.com/repos/matplotlib/matplotlib/git/trees/99d8900eacaad01b1ff6e5d482e4e17683dd36be?recursive=true
    09:44:51.09 <<< Return value from get_repo_tree: ('{"sha":"99d8900eacaad01b1ff6e5d482e4e17683dd36be...1befdb06113c867356e4bea861e"}],"truncated":false}', '99d8900eacaad01b1ff6e5d482e4e17683dd36be')
    
    09:44:51.10 <<< Return value from Tracer.__call__.<locals>.simple_wrapper: ('{"sha":"99d8900eacaad01b1ff6e5d482e4e17683dd36be...1befdb06113c867356e4bea861e"}],"truncated":false}', '99d8900eacaad01b1ff6e5d482e4e17683dd36be')
    09:44:51.10  169 |                 return function(*args, **kwargs)
    09:44:51.10 ...................... args = ('matplotlib', 'matplotlib', '99d8900eacaad01b1ff6e5d482e4e17683dd36be')
    09:44:51.10 ...................... len(args) = 3
    09:44:51.10 ...................... kwargs = {'logged_in_user': <SimpleLazyObject: <User: andy22>>}
    09:44:51.10 ...................... len(kwargs) = 1
    09:44:51.10 ...................... function = <function get_repo_tree at 0x10d71b7b8>
    09:44:51.10 ...................... self = <snoop.configuration.Config.__init__.<locals>.ConfiguredTracer object at 0x10d5bd358>
    09:44:51.10 <<< Exit with block in Tracer.__call__.<locals>.simple_wrapper
    

    When the second snoop config is configured to go soley to a file,

    snoop.install()
    config = snoop.Config(out="junk.txt")
    

    the nice normal snoop output fails to appear in stderr at all, and the two unwanted "tracer call outputs" appear in stderr instead. Output does thankfully appear in the output file.

    I'm assuming I am using snoop correctly, by adding the two decorators one after the other, before the target def. If I don't add the second snoop decorator then it doesn't take effect, so it seems that must be the way to do it.

    opened by abulka 4
  • Snoop doesn't load source code from compiled functions

    Snoop doesn't load source code from compiled functions

    I'm trying to debug functions, generated from the source in runtime, but for some reason, snoop is unable to show the source code of such function. At the same time it shows variables and nested functions source - see an example below. Please, suggest, if I'm doing something wrong? Thanks!

    Script output

        22:03:23.24 >>> Call to main in File "func_code", line 1
        22:03:23.24    1 | SOURCE IS UNAVAILABLE
        22:03:23.24    2 | SOURCE IS UNAVAILABLE
        22:03:23.24 ...... a = 2
        22:03:23.24    3 | SOURCE IS UNAVAILABLE
        22:03:23.24 ...... b = 3
        22:03:23.24    5 | SOURCE IS UNAVAILABLE
            22:03:23.33 >>> Call to Random.randint in File "/usr/local/Cellar/[email protected]/3.8.2/Frameworks/Python.framework/Versions/3.8/lib/python3.8/random.py", line 244
            22:03:23.33 .......... self = <random.Random object at 0x7ff952003810>
            22:03:23.33 .......... a = 1
            22:03:23.33 .......... b = 100
            22:03:23.33  244 |     def randint(self, a, b):
            22:03:23.34  248 |         return self.randrange(a, b+1)
            22:03:23.34 <<< Return value from Random.randint: 20
        22:03:23.34    5 | SOURCE IS UNAVAILABLE
        22:03:23.34 ...... c = 25
        22:03:23.34    7 | SOURCE IS UNAVAILABLE
        22:03:23.34 <<< Return value from main: 25
    

    Script code

    import types
    import random
    
    import snoop
    
    
    func_text = """def main():
            a = 2
            b = 3
            c = a + b + random.randint(1, 100)
            return c"""
    
    func_code = compile(
        source=func_text,
        filename="func_code",
        mode='exec',
    )
    
    tracer = snoop.snoop(depth=3)
    
    func = types.FunctionType(
        func_code.co_consts[0],
        {
            "random": random,
            "tracer": tracer,
        },
        'func'
    )
    
    
    if __name__ == '__main__':
        with tracer:
            func()
    
    opened by vikt0rs 3
  • Use pprintpp if insalled

    Use pprintpp if insalled

    It would be nice if pprintpp would be used for pretty printing values if installed instead of build-in pprint. Or at least pretty printing function should be configurable.

    pprintpp gives more readable output.

    opened by sirex 3
  • Filter variables to output when using `with snoop:` ?

    Filter variables to output when using `with snoop:` ?

    I tried to run "with snoop" on a part of my code and it printed this in the console

    I wish there's some way to filter the variables to output when using "with snoop:" so I can remove some unnecessary output such as "object variables" and "class instance"

    This is the part code I run with "with snoop":

    with snoop:
        for files in sourcefiles:
            for file_type in images:
                if files.endswith(file_type):
                    path = os.path.join(dir, files)
                    for element in result:
                        if " " in element:
                            for element in element.split(" "):
                                filter(element)
                        else:
                            filter(element)
                    fil_result.append("\n\n")
                    per_picture.append(fil_result)
                    fil_result = []
    

    Then this is the result to the console:

    07:17:12.34 >>> Enter with block in <module> in File "D:\OCR\New folder\safe prototype gui.py", line 347
    07:17:12.34 ...... __name__ = '__main__'
    07:17:12.34 ...... __doc__ = None
    07:17:12.34 ...... __package__ = None
    07:17:12.34 ...... __loader__ = <_frozen_importlib_external.SourceFileLoader object at 0x0000021346836CD0>
    07:17:12.34 ...... __spec__ = None
    07:17:12.34 ...... __annotations__ = {}
    07:17:12.34 ...... __builtins__ = <module 'builtins' (built-in)>
    07:17:12.34 ...... __file__ = 'D:\\OCR\\New folder\\safe prototype gui.py'
    07:17:12.34 ...... __cached__ = None
    07:17:12.34 ...... QApplication = <class 'PyQt5.QtWidgets.QApplication'>
    07:17:12.34 ...... QWidget = <class 'PyQt5.QtWidgets.QWidget'>
    07:17:12.34 ...... QFileDialog = <class 'PyQt5.QtWidgets.QFileDialog'>
    07:17:12.34 ...... QLineEdit = <class 'PyQt5.QtWidgets.QLineEdit'>
    07:17:12.34 ...... QComboBox = <class 'PyQt5.QtWidgets.QComboBox'>
    07:17:12.34 ...... QTableWidgetSelectionRange = <class 'PyQt5.QtWidgets.QTableWidgetSelectionRange'>
    07:17:12.34 ...... QColor = <class 'PyQt5.QtGui.QColor'>
    07:17:12.34 ...... QFont = <class 'PyQt5.QtGui.QFont'>
    07:17:12.34 ...... QStandardItemModel = <class 'PyQt5.QtGui.QStandardItemModel'>
    07:17:12.34 ...... QStandardItem = <class 'PyQt5.QtGui.QStandardItem'>
    07:17:12.34 ...... uic = <module 'PyQt5.uic' from 'C:\\Users\\Eliaz\\AppD...39\\lib\\site-packages\\PyQt5\\uic\\__init__.py'>
    07:17:12.34 ...... QtWidgets = <module 'PyQt5.QtWidgets' from 'C:\\Users\\Eliaz...hon39\\lib\\site-packages\\PyQt5\\QtWidgets.pyd'>
    07:17:12.34 ...... Qt = <class 'PyQt5.QtCore.Qt'>
    07:17:12.34 ...... QSortFilterProxyModel = <class 'PyQt5.QtCore.QSortFilterProxyModel'>
    07:17:12.34 ...... QtCore = <module 'PyQt5.QtCore' from 'C:\\Users\\Eliaz\\A...Python39\\lib\\site-packages\\PyQt5\\QtCore.pyd'>
    07:17:12.34 ...... QtGui = <module 'PyQt5.QtGui' from 'C:\\Users\\Eliaz\\Ap...\Python39\\lib\\site-packages\\PyQt5\\QtGui.pyd'>
    07:17:12.34 ...... easyocr = <module 'easyocr' from 'C:\\Users\\Eliaz\\AppDat...hon39\\lib\\site-packages\\easyocr\\__init__.py'>
    07:17:12.34 ...... sys = <module 'sys' (built-in)>
    07:17:12.34 ...... os = <module 'os' from 'C:\\Users\\Eliaz\\AppData\\Local\\Programs\\Python\\Python39\\lib\\os.py'>
    07:17:12.34 ...... ic = <icecream.icecream.IceCreamDebugger object at 0x000002135FCC2940>
    07:17:12.34 ...... snoop = <class 'snoop.configuration.Config.__init__.<locals>.ConfiguredTracer'>
    07:17:12.34 ...... ps = <module 'pysnooper' from 'C:\\Users\\Eliaz\\AppD...n39\\lib\\site-packages\\pysnooper\\__init__.py'>
    07:17:12.34 ...... DialogApp = <class '__main__.DialogApp'>
    07:17:12.34 ...... MyApp = <class '__main__.MyApp'>
    07:17:12.34 ...... filter = <function filter at 0x000002134687DF70>
    07:17:12.34 ...... MyAppGui = <function MyAppGui at 0x000002135FE6EF70>
    07:17:12.34 ...... app = <PyQt5.QtWidgets.QApplication object at 0x000002135FE6F040>
    07:17:12.34 ...... demo = <__main__.DialogApp object at 0x000002135FE6F0D0>
    07:17:12.34 ...... replaces = {'k': 'rep', 'as': 'like'}
    07:17:12.34 ...... len(replaces) = 2
    07:17:12.34 ...... rep = <_io.TextIOWrapper name='D:\\OCR\\dict.txt' mode='r' encoding='cp1252'>
    07:17:12.34 ...... line = 'earth\n'
    07:17:12.34 ...... key = 'as'
    07:17:12.34 ...... value = 'like'
    07:17:12.34 ...... ignores = {'earth', 'lithosphere', 'The', 'and', 'properties', 'Layers', 'that', 'a', 'categorized', 'temperature,', ...}
    07:17:12.34 ...... len(ignores) = 23
    07:17:12.34 ...... ign = <_io.TextIOWrapper name='D:\\OCR\\ignores.txt' mode='r' encoding='cp1252'>
    07:17:12.34 ...... val = 'earth'
    07:17:12.34 ...... textfile = <_io.TextIOWrapper name='D:\\OCR\\ignore.txt' mode='w' encoding='cp1252'>
    07:17:12.34 ...... images = ['.tiff', '.gif', '.png', '.eps', '.bmp', '.jpg', '.jpf', '.jpeg', '.ppm']
    07:17:12.34 ...... len(images) = 9
    07:17:12.34 ...... delete = set()
    07:17:12.34 ...... unknown_words = set()
    07:17:12.34 ...... fil_result = []
    07:17:12.34 ...... result = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', ..., 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z']
    07:17:12.34 ...... len(result) = 26
    07:17:12.34 ...... list_of_strings_from_textedit = []
    07:17:12.34 ...... per_picture = []
    07:17:12.34 ...... dir = 'D:\\OCR\\test'
    07:17:12.34 ...... sourcefiles = ['2021-09-15 08_06_48-(2) Facebook - Vivaldi.jpg', '2021-09-15 08_10_38-(2) Facebook - Vivaldi.jpg', 'textfile.txt']
    07:17:12.34 ...... len(sourcefiles) = 3
    07:17:12.34  348 |     for files in sourcefiles:
    07:17:12.34 .......... files = '2021-09-15 08_06_48-(2) Facebook - Vivaldi.jpg'
    07:17:12.34  349 |         for file_type in images:
    07:17:12.34 .............. file_type = '.tiff'
    07:17:12.34  350 |             if files.endswith(file_type):
    07:17:12.34  349 |         for file_type in images:
    07:17:12.34 .............. file_type = '.gif'
    07:17:12.34  350 |             if files.endswith(file_type):
    07:17:12.35  349 |         for file_type in images:
    07:17:12.35 .............. file_type = '.png'
    07:17:12.35  350 |             if files.endswith(file_type):
    07:17:12.35  349 |         for file_type in images:
    07:17:12.35 .............. file_type = '.eps'
    07:17:12.35  350 |             if files.endswith(file_type):
    07:17:12.35  349 |         for file_type in images:
    07:17:12.35 .............. file_type = '.bmp'
    07:17:12.35  350 |             if files.endswith(file_type):
    07:17:12.35  349 |         for file_type in images:
    07:17:12.35 .............. file_type = '.jpg'
    07:17:12.35  350 |             if files.endswith(file_type):
    07:17:12.35  351 |                 path = os.path.join(dir, files)
    07:17:12.35 ...................... path = 'D:\\OCR\\test\\2021-09-15 08_06_48-(2) Facebook - Vivaldi.jpg'
    07:17:12.35 ...................... len(path) = 58
    07:17:12.35  355 |                 for element in result:
    07:17:12.35 ...................... element = 'a'
    07:17:12.35  356 |                     if " " in element:
    07:17:12.35  360 |                         filter(element)
    07:17:12.35 .............................. unknown_words = {'a'}
    07:17:12.35 .............................. len(unknown_words) = 1
    07:17:12.35 .............................. fil_result = ['a', ' ']
    07:17:12.35 .............................. len(fil_result) = 2
    07:17:12.35 .............................. __warningregistry__ = {'version': 22}
    07:17:12.35 .............................. len(__warningregistry__) = 1
    07:17:12.35  355 |                 for element in result:
    07:17:12.35 ...................... element = 'b'
    07:17:12.35  356 |                     if " " in element:
    07:17:12.35  360 |                         filter(element)
    07:17:12.35 .............................. unknown_words = {'b', 'a'}
    07:17:12.35 .............................. len(unknown_words) = 2
    07:17:12.35 .............................. fil_result = ['a', ' ', 'b', ' ']
    07:17:12.35 .............................. len(fil_result) = 4
    07:17:12.35  355 |                 for element in result:
    07:17:12.35 ...................... element = 'c'
    07:17:12.35  356 |                     if " " in element:
    07:17:12.35  360 |                         filter(element)
    07:17:12.35 .............................. unknown_words = {'b', 'a', 'c'}
    07:17:12.35 .............................. len(unknown_words) = 3
    07:17:12.35 .............................. fil_result = ['a', ' ', 'b', ' ', 'c', ' ']
    07:17:12.35 .............................. len(fil_result) = 6
    07:17:12.35  355 |                 for element in result:
    07:17:12.36 ...................... element = 'd'
    07:17:12.36  356 |                     if " " in element:
    07:17:12.36  360 |                         filter(element)
    07:17:12.36 .............................. unknown_words = {'b', 'a', 'c', 'd'}
    07:17:12.36 .............................. len(unknown_words) = 4
    07:17:12.36 .............................. fil_result = ['a', ' ', 'b', ' ', 'c', ' ', 'd', ' ']
    07:17:12.36 .............................. len(fil_result) = 8
    07:17:12.36  355 |                 for element in result:
    07:17:12.36 ...................... element = 'e'
    07:17:12.36  356 |                     if " " in element:
    07:17:12.36  360 |                         filter(element)
    07:17:12.36 .............................. unknown_words = {'b', 'c', 'd', 'a', 'e'}
    07:17:12.36 .............................. len(unknown_words) = 5
    07:17:12.36 .............................. fil_result = ['a', ' ', 'b', ' ', 'c', ' ', 'd', ' ', 'e', ' ']
    07:17:12.36 .............................. len(fil_result) = 10
    07:17:12.36  355 |                 for element in result:
    07:17:12.36 ...................... element = 'f'
    07:17:12.36  356 |                     if " " in element:
    07:17:12.36  360 |                         filter(element)
    07:17:12.36 .............................. unknown_words = {'b', 'c', 'd', 'a', 'f', 'e'}
    07:17:12.36 .............................. len(unknown_words) = 6
    07:17:12.36 .............................. fil_result = ['a', ' ', 'b', ' ', 'c', ' ', 'd', ' ', 'e', ' ', 'f', ' ']
    07:17:12.36 .............................. len(fil_result) = 12
    07:17:12.36  355 |                 for element in result:
    07:17:12.36 ...................... element = 'g'
    07:17:12.36  356 |                     if " " in element:
    07:17:12.36  360 |                         filter(element)
    07:17:12.36 .............................. unknown_words = {'b', 'c', 'd', 'a', 'g', 'f', 'e'}
    07:17:12.36 .............................. len(unknown_words) = 7
    07:17:12.36 .............................. fil_result = ['a', ' ', 'b', ' ', 'c', ' ', 'd', ' ', 'e', ' ', 'f', ' ', 'g', ' ']
    07:17:12.36 .............................. len(fil_result) = 14
    07:17:12.36  355 |                 for element in result:
    07:17:12.36 ...................... element = 'h'
    07:17:12.36  356 |                     if " " in element:
    07:17:12.36  360 |                         filter(element)
    07:17:12.36 .............................. unknown_words = {'b', 'c', 'd', 'a', 'g', 'f', 'h', 'e'}
    07:17:12.36 .............................. len(unknown_words) = 8
    07:17:12.36 .............................. fil_result = ['a', ' ', 'b', ' ', 'c', ' ', 'd', ' ', 'e', ' ', 'f', ' ', 'g', ' ', 'h', ' ']
    07:17:12.36 .............................. len(fil_result) = 16
    07:17:12.36  355 |                 for element in result:
    07:17:12.36 ...................... element = 'i'
    07:17:12.36  356 |                     if " " in element:
    07:17:12.36  360 |                         filter(element)
    07:17:12.38 .............................. unknown_words = {'b', 'c', 'd', 'a', 'i', 'g', 'f', 'h', 'e'}
    07:17:12.38 .............................. len(unknown_words) = 9
    07:17:12.38 .............................. fil_result = ['a', ' ', 'b', ' ', 'c', ' ', 'd', ' ', 'e', ' ', 'f', ' ', 'g', ' ', 'h', ' ', 'i', ' ']
    07:17:12.38 .............................. len(fil_result) = 18
    07:17:12.38  355 |                 for element in result:
    07:17:12.38 ...................... element = 'j'
    07:17:12.38  356 |                     if " " in element:
    07:17:12.38  360 |                         filter(element)
    07:17:12.38 .............................. unknown_words = {'b', 'c', 'd', 'a', 'i', 'g', 'f', 'j', 'h', 'e'}
    07:17:12.38 .............................. len(unknown_words) = 10
    07:17:12.38 .............................. fil_result = ['a', ' ', 'b', ' ', 'c', ' ', 'd', ' ', 'e', ' ', ..., ' ', 'g', ' ', 'h', ' ', 'i', ' ', 'j', ' ']
    07:17:12.38 .............................. len(fil_result) = 20
    07:17:12.38  355 |                 for element in result:
    07:17:12.38 ...................... element = 'k'
    07:17:12.38  356 |                     if " " in element:
    07:17:12.38  360 |                         filter(element)
    07:17:12.38 .............................. unknown_words = {'b', 'k', 'c', 'd', 'a', 'i', 'g', 'f', 'j', 'h', 'e'}
    07:17:12.38 .............................. len(unknown_words) = 11
    07:17:12.38 .............................. fil_result = ['a', ' ', 'b', ' ', 'c', ' ', 'd', ' ', 'e', ' ', ..., ' ', 'h', ' ', 'i', ' ', 'j', ' ', 'k', ' ']
    07:17:12.38 .............................. len(fil_result) = 22
    07:17:12.38  355 |                 for element in result:
    07:17:12.38 ...................... element = 'l'
    07:17:12.38  356 |                     if " " in element:
    07:17:12.38  360 |                         filter(element)
    07:17:12.38 .............................. unknown_words = {'b', 'k', 'c', 'l', 'd', 'a', 'i', 'g', 'f', 'j', 'h', 'e'}
    07:17:12.38 .............................. len(unknown_words) = 12
    07:17:12.38 .............................. fil_result = ['a', ' ', 'b', ' ', 'c', ' ', 'd', ' ', 'e', ' ', ..., ' ', 'i', ' ', 'j', ' ', 'k', ' ', 'l', ' ']
    07:17:12.38 .............................. len(fil_result) = 24
    07:17:12.38  355 |                 for element in result:
    07:17:12.38 ...................... element = 'm'
    07:17:12.38  356 |                     if " " in element:
    07:17:12.38  360 |                         filter(element)
    07:17:12.38 .............................. unknown_words = {'b', 'k', 'c', 'l', 'd', 'a', 'i', 'g', 'f', 'j', 'h', 'm', 'e'}
    07:17:12.38 .............................. len(unknown_words) = 13
    07:17:12.38 .............................. fil_result = ['a', ' ', 'b', ' ', 'c', ' ', 'd', ' ', 'e', ' ', ..., ' ', 'j', ' ', 'k', ' ', 'l', ' ', 'm', ' ']
    07:17:12.38 .............................. len(fil_result) = 26
    07:17:12.38  355 |                 for element in result:
    07:17:12.38 ...................... element = 'n'
    07:17:12.38  356 |                     if " " in element:
    07:17:12.38  360 |                         filter(element)
    07:17:12.38 .............................. unknown_words = {'b', 'k', 'c', 'l', 'd', 'a', 'i', 'g', 'f', 'j', 'h', 'n', 'm', 'e'}
    07:17:12.38 .............................. len(unknown_words) = 14
    07:17:12.38 .............................. fil_result = ['a', ' ', 'b', ' ', 'c', ' ', 'd', ' ', 'e', ' ', ..., ' ', 'k', ' ', 'l', ' ', 'm', ' ', 'n', ' ']
    07:17:12.38 .............................. len(fil_result) = 28
    07:17:12.38  355 |                 for element in result:
    07:17:12.38 ...................... element = 'o'
    07:17:12.38  356 |                     if " " in element:
    07:17:12.38  360 |                         filter(element)
    07:17:12.40 .............................. unknown_words = {'b', 'k', 'c', 'l', 'd', 'a', 'i', 'g', 'f', 'j', 'h', 'n', 'm', 'e', 'o'}
    07:17:12.40 .............................. len(unknown_words) = 15
    07:17:12.40 .............................. fil_result = ['a', ' ', 'b', ' ', 'c', ' ', 'd', ' ', 'e', ' ', ..., ' ', 'l', ' ', 'm', ' ', 'n', ' ', 'o', ' ']
    07:17:12.40 .............................. len(fil_result) = 30
    07:17:12.40  355 |                 for element in result:
    07:17:12.40 ...................... element = 'p'
    07:17:12.40  356 |                     if " " in element:
    07:17:12.40  360 |                         filter(element)
    07:17:12.40 .............................. unknown_words = {'b', 'k', 'c', 'l', 'd', 'p', 'a', 'i', 'g', 'f', 'j', 'h', 'n', 'm', 'e', 'o'}
    07:17:12.40 .............................. len(unknown_words) = 16
    07:17:12.40 .............................. fil_result = ['a', ' ', 'b', ' ', 'c', ' ', 'd', ' ', 'e', ' ', ..., ' ', 'm', ' ', 'n', ' ', 'o', ' ', 'p', ' ']
    07:17:12.40 .............................. len(fil_result) = 32
    07:17:12.40  355 |                 for element in result:
    07:17:12.40 ...................... element = 'q'
    07:17:12.40  356 |                     if " " in element:
    07:17:12.40  360 |                         filter(element)
    07:17:12.40 .............................. unknown_words = {'b', 'k', 'c', 'q', 'l', 'd', 'p', 'a', 'i', 'g', 'f', 'j', 'h', 'n', 'm', 'e', 'o'}
    07:17:12.40 .............................. len(unknown_words) = 17
    07:17:12.40 .............................. fil_result = ['a', ' ', 'b', ' ', 'c', ' ', 'd', ' ', 'e', ' ', ..., ' ', 'n', ' ', 'o', ' ', 'p', ' ', 'q', ' ']
    07:17:12.40 .............................. len(fil_result) = 34
    07:17:12.40  355 |                 for element in result:
    07:17:12.40 ...................... element = 'r'
    07:17:12.40  356 |                     if " " in element:
    07:17:12.40  360 |                         filter(element)
    07:17:12.40 .............................. unknown_words = {'b', 'k', 'c', 'q', 'l', 'd', 'r', 'p', 'a', 'i', 'g', 'f', 'j', 'h', 'n', 'm', 'e', 'o'}
    07:17:12.40 .............................. len(unknown_words) = 18
    07:17:12.40 .............................. fil_result = ['a', ' ', 'b', ' ', 'c', ' ', 'd', ' ', 'e', ' ', ..., ' ', 'o', ' ', 'p', ' ', 'q', ' ', 'r', ' ']
    07:17:12.40 .............................. len(fil_result) = 36
    07:17:12.40  355 |                 for element in result:
    07:17:12.40 ...................... element = 's'
    07:17:12.40  356 |                     if " " in element:
    07:17:12.40  360 |                         filter(element)
    07:17:12.41 .............................. unknown_words = {'b', 'k', 'd', 'g', 'f', 'j', 'n', 'r', 'p', 'a', 'e', 'c', 'l', 's', 'i', 'h', 'o', 'q', 'm'}
    07:17:12.41 .............................. len(unknown_words) = 19
    07:17:12.41 .............................. fil_result = ['a', ' ', 'b', ' ', 'c', ' ', 'd', ' ', 'e', ' ', ..., ' ', 'p', ' ', 'q', ' ', 'r', ' ', 's', ' ']
    07:17:12.41 .............................. len(fil_result) = 38
    07:17:12.41  355 |                 for element in result:
    07:17:12.41 ...................... element = 't'
    07:17:12.41  356 |                     if " " in element:
    07:17:12.41  360 |                         filter(element)
    07:17:12.41 .............................. unknown_words = {'b', 'k', 'd', 'g', 'f', 'j', 'n', 'r', 'p', 'a', 't', 'e', 'c', 'l', 's', 'i', 'h', 'o', 'q', ...}
    07:17:12.41 .............................. len(unknown_words) = 20
    07:17:12.41 .............................. fil_result = ['a', ' ', 'b', ' ', 'c', ' ', 'd', ' ', 'e', ' ', ..., ' ', 'q', ' ', 'r', ' ', 's', ' ', 't', ' ']
    07:17:12.41 .............................. len(fil_result) = 40
    07:17:12.41  355 |                 for element in result:
    07:17:12.41 ...................... element = 'u'
    07:17:12.41  356 |                     if " " in element:
    07:17:12.41  360 |                         filter(element)
    07:17:12.41 .............................. len(unknown_words) = 21
    07:17:12.41 .............................. fil_result = ['a', ' ', 'b', ' ', 'c', ' ', 'd', ' ', 'e', ' ', ..., ' ', 'r', ' ', 's', ' ', 't', ' ', 'u', ' ']
    07:17:12.41 .............................. len(fil_result) = 42
    07:17:12.41  355 |                 for element in result:
    07:17:12.41 ...................... element = 'v'
    07:17:12.41  356 |                     if " " in element:
    07:17:12.41  360 |                         filter(element)
    07:17:12.41 .............................. unknown_words = {'b', 'k', 'd', 'g', 'f', 'j', 'n', 'v', 'r', 'p', 'a', 't', 'e', 'c', 'l', 's', 'i', 'h', 'o', ...}
    07:17:12.41 .............................. len(unknown_words) = 22
    07:17:12.41 .............................. fil_result = ['a', ' ', 'b', ' ', 'c', ' ', 'd', ' ', 'e', ' ', ..., ' ', 's', ' ', 't', ' ', 'u', ' ', 'v', ' ']
    07:17:12.41 .............................. len(fil_result) = 44
    07:17:12.41  355 |                 for element in result:
    07:17:12.42 ...................... element = 'w'
    07:17:12.42  356 |                     if " " in element:
    07:17:12.42  360 |                         filter(element)
    07:17:12.42 .............................. unknown_words = {'b', 'k', 'd', 'w', 'g', 'f', 'j', 'n', 'v', 'r', 'p', 'a', 't', 'e', 'c', 'l', 's', 'i', 'h', ...}
    07:17:12.42 .............................. len(unknown_words) = 23
    07:17:12.42 .............................. fil_result = ['a', ' ', 'b', ' ', 'c', ' ', 'd', ' ', 'e', ' ', ..., ' ', 't', ' ', 'u', ' ', 'v', ' ', 'w', ' ']
    07:17:12.42 .............................. len(fil_result) = 46
    07:17:12.42  355 |                 for element in result:
    07:17:12.42 ...................... element = 'x'
    07:17:12.42  356 |                     if " " in element:
    07:17:12.42  360 |                         filter(element)
    07:17:12.42 .............................. unknown_words = {'b', 'k', 'd', 'w', 'g', 'f', 'j', 'n', 'v', 'r', 'p', 'a', 'x', 't', 'e', 'c', 'l', 's', 'i', ...}
    07:17:12.42 .............................. len(unknown_words) = 24
    07:17:12.42 .............................. fil_result = ['a', ' ', 'b', ' ', 'c', ' ', 'd', ' ', 'e', ' ', ..., ' ', 'u', ' ', 'v', ' ', 'w', ' ', 'x', ' ']
    07:17:12.42 .............................. len(fil_result) = 48
    07:17:12.42  355 |                 for element in result:
    07:17:12.42 ...................... element = 'y'
    07:17:12.42  356 |                     if " " in element:
    07:17:12.42  360 |                         filter(element)
    07:17:12.42 .............................. unknown_words = {'b', 'k', 'd', 'w', 'g', 'f', 'j', 'n', 'y', 'v', 'r', 'p', 'a', 'x', 't', 'e', 'c', 'l', 's', ...}
    07:17:12.42 .............................. len(unknown_words) = 25
    07:17:12.42 .............................. fil_result = ['a', ' ', 'b', ' ', 'c', ' ', 'd', ' ', 'e', ' ', ..., ' ', 'v', ' ', 'w', ' ', 'x', ' ', 'y', ' ']
    07:17:12.42 .............................. len(fil_result) = 50
    07:17:12.42  355 |                 for element in result:
    07:17:12.42 ...................... element = 'z'
    07:17:12.42  356 |                     if " " in element:
    07:17:12.42  360 |                         filter(element)
    07:17:12.43 .............................. len(unknown_words) = 26
    07:17:12.43 .............................. fil_result = ['a', ' ', 'b', ' ', 'c', ' ', 'd', ' ', 'e', ' ', ..., ' ', 'w', ' ', 'x', ' ', 'y', ' ', 'z', ' ']
    07:17:12.43 .............................. len(fil_result) = 52
    07:17:12.43  355 |                 for element in result:
    07:17:12.43  362 |                 fil_result.append("\n\n")
    07:17:12.43 ...................... fil_result = ['a', ' ', 'b', ' ', 'c', ' ', 'd', ' ', 'e', ' ', ..., 'w', ' ', 'x', ' ', 'y', ' ', 'z', ' ', '\n\n']
    07:17:12.43 ...................... len(fil_result) = 53
    07:17:12.43  363 |                 per_picture.append(fil_result)
    07:17:12.43 ...................... per_picture = [['a', ' ', 'b', ..., 'z', ' ', '\n\n']]
    07:17:12.43 ...................... len(per_picture) = 1
    07:17:12.43  364 |                 fil_result = []
    07:17:12.43  349 |         for file_type in images:
    07:17:12.43 .............. file_type = '.jpf'
    07:17:12.43  350 |             if files.endswith(file_type):
    07:17:12.43  349 |         for file_type in images:
    07:17:12.43 .............. file_type = '.jpeg'
    07:17:12.43  350 |             if files.endswith(file_type):
    07:17:12.43  349 |         for file_type in images:
    07:17:12.43 .............. file_type = '.ppm'
    07:17:12.43  350 |             if files.endswith(file_type):
    07:17:12.43  349 |         for file_type in images:
    07:17:12.43  348 |     for files in sourcefiles:
    07:17:12.44 .......... files = '2021-09-15 08_10_38-(2) Facebook - Vivaldi.jpg'
    07:17:12.44  349 |         for file_type in images:
    07:17:12.44 .............. file_type = '.tiff'
    07:17:12.44  350 |             if files.endswith(file_type):
    07:17:12.44  349 |         for file_type in images:
    07:17:12.44 .............. file_type = '.gif'
    07:17:12.44  350 |             if files.endswith(file_type):
    07:17:12.44  349 |         for file_type in images:
    07:17:12.44 .............. file_type = '.png'
    07:17:12.44  350 |             if files.endswith(file_type):
    07:17:12.44  349 |         for file_type in images:
    07:17:12.44 .............. file_type = '.eps'
    07:17:12.44  350 |             if files.endswith(file_type):
    07:17:12.44  349 |         for file_type in images:
    07:17:12.44 .............. file_type = '.bmp'
    07:17:12.44  350 |             if files.endswith(file_type):
    07:17:12.44  349 |         for file_type in images:
    07:17:12.44 .............. file_type = '.jpg'
    07:17:12.44  350 |             if files.endswith(file_type):
    07:17:12.45  351 |                 path = os.path.join(dir, files)
    07:17:12.45 ...................... path = 'D:\\OCR\\test\\2021-09-15 08_10_38-(2) Facebook - Vivaldi.jpg'
    07:17:12.45  355 |                 for element in result:
    07:17:12.45 ...................... element = 'a'
    07:17:12.45  356 |                     if " " in element:
    07:17:12.45  360 |                         filter(element)
    07:17:12.45 .............................. fil_result = ['a', ' ']
    07:17:12.45 .............................. len(fil_result) = 2
    07:17:12.45  355 |                 for element in result:
    07:17:12.45 ...................... element = 'b'
    07:17:12.45  356 |                     if " " in element:
    07:17:12.45  360 |                         filter(element)
    07:17:12.45 .............................. fil_result = ['a', ' ', 'b', ' ']
    07:17:12.45 .............................. len(fil_result) = 4
    07:17:12.45  355 |                 for element in result:
    07:17:12.45 ...................... element = 'c'
    07:17:12.45  356 |                     if " " in element:
    07:17:12.45  360 |                         filter(element)
    07:17:12.45 .............................. fil_result = ['a', ' ', 'b', ' ', 'c', ' ']
    07:17:12.45 .............................. len(fil_result) = 6
    07:17:12.45  355 |                 for element in result:
    07:17:12.45 ...................... element = 'd'
    07:17:12.45  356 |                     if " " in element:
    07:17:12.45  360 |                         filter(element)
    07:17:12.45 .............................. fil_result = ['a', ' ', 'b', ' ', 'c', ' ', 'd', ' ']
    07:17:12.45 .............................. len(fil_result) = 8
    07:17:12.45  355 |                 for element in result:
    07:17:12.45 ...................... element = 'e'
    07:17:12.45  356 |                     if " " in element:
    07:17:12.45  360 |                         filter(element)
    07:17:12.45 .............................. fil_result = ['a', ' ', 'b', ' ', 'c', ' ', 'd', ' ', 'e', ' ']
    07:17:12.45 .............................. len(fil_result) = 10
    07:17:12.45  355 |                 for element in result:
    07:17:12.45 ...................... element = 'f'
    07:17:12.45  356 |                     if " " in element:
    07:17:12.46  360 |                         filter(element)
    07:17:12.46 .............................. fil_result = ['a', ' ', 'b', ' ', 'c', ' ', 'd', ' ', 'e', ' ', 'f', ' ']
    07:17:12.46 .............................. len(fil_result) = 12
    07:17:12.46  355 |                 for element in result:
    07:17:12.46 ...................... element = 'g'
    07:17:12.46  356 |                     if " " in element:
    07:17:12.46  360 |                         filter(element)
    07:17:12.46 .............................. fil_result = ['a', ' ', 'b', ' ', 'c', ' ', 'd', ' ', 'e', ' ', 'f', ' ', 'g', ' ']
    07:17:12.46 .............................. len(fil_result) = 14
    07:17:12.46  355 |                 for element in result:
    07:17:12.46 ...................... element = 'h'
    07:17:12.46  356 |                     if " " in element:
    07:17:12.46  360 |                         filter(element)
    07:17:12.46 .............................. fil_result = ['a', ' ', 'b', ' ', 'c', ' ', 'd', ' ', 'e', ' ', 'f', ' ', 'g', ' ', 'h', ' ']
    07:17:12.46 .............................. len(fil_result) = 16
    07:17:12.46  355 |                 for element in result:
    07:17:12.46 ...................... element = 'i'
    07:17:12.46  356 |                     if " " in element:
    07:17:12.46  360 |                         filter(element)
    07:17:12.46 .............................. fil_result = ['a', ' ', 'b', ' ', 'c', ' ', 'd', ' ', 'e', ' ', 'f', ' ', 'g', ' ', 'h', ' ', 'i', ' ']
    07:17:12.46 .............................. len(fil_result) = 18
    07:17:12.46  355 |                 for element in result:
    07:17:12.46 ...................... element = 'j'
    07:17:12.46  356 |                     if " " in element:
    07:17:12.46  360 |                         filter(element)
    07:17:12.46 .............................. fil_result = ['a', ' ', 'b', ' ', 'c', ' ', 'd', ' ', 'e', ' ', ..., ' ', 'g', ' ', 'h', ' ', 'i', ' ', 'j', ' ']
    07:17:12.46 .............................. len(fil_result) = 20
    07:17:12.46  355 |                 for element in result:
    07:17:12.46 ...................... element = 'k'
    07:17:12.46  356 |                     if " " in element:
    07:17:12.46  360 |                         filter(element)
    07:17:12.46 .............................. fil_result = ['a', ' ', 'b', ' ', 'c', ' ', 'd', ' ', 'e', ' ', ..., ' ', 'h', ' ', 'i', ' ', 'j', ' ', 'k', ' ']
    07:17:12.46 .............................. len(fil_result) = 22
    07:17:12.46  355 |                 for element in result:
    07:17:12.48 ...................... element = 'l'
    07:17:12.48  356 |                     if " " in element:
    07:17:12.48  360 |                         filter(element)
    07:17:12.48 .............................. fil_result = ['a', ' ', 'b', ' ', 'c', ' ', 'd', ' ', 'e', ' ', ..., ' ', 'i', ' ', 'j', ' ', 'k', ' ', 'l', ' ']
    07:17:12.48 .............................. len(fil_result) = 24
    07:17:12.48  355 |                 for element in result:
    07:17:12.48 ...................... element = 'm'
    07:17:12.48  356 |                     if " " in element:
    07:17:12.48  360 |                         filter(element)
    07:17:12.48 .............................. fil_result = ['a', ' ', 'b', ' ', 'c', ' ', 'd', ' ', 'e', ' ', ..., ' ', 'j', ' ', 'k', ' ', 'l', ' ', 'm', ' ']
    07:17:12.48 .............................. len(fil_result) = 26
    07:17:12.48  355 |                 for element in result:
    07:17:12.48 ...................... element = 'n'
    07:17:12.48  356 |                     if " " in element:
    07:17:12.48  360 |                         filter(element)
    07:17:12.48 .............................. fil_result = ['a', ' ', 'b', ' ', 'c', ' ', 'd', ' ', 'e', ' ', ..., ' ', 'k', ' ', 'l', ' ', 'm', ' ', 'n', ' ']
    07:17:12.48 .............................. len(fil_result) = 28
    07:17:12.48  355 |                 for element in result:
    07:17:12.48 ...................... element = 'o'
    07:17:12.48  356 |                     if " " in element:
    07:17:12.48  360 |                         filter(element)
    07:17:12.49 .............................. fil_result = ['a', ' ', 'b', ' ', 'c', ' ', 'd', ' ', 'e', ' ', ..., ' ', 'l', ' ', 'm', ' ', 'n', ' ', 'o', ' ']
    07:17:12.49 .............................. len(fil_result) = 30
    07:17:12.49  355 |                 for element in result:
    07:17:12.49 ...................... element = 'p'
    07:17:12.49  356 |                     if " " in element:
    07:17:12.50  360 |                         filter(element)
    07:17:12.50 .............................. fil_result = ['a', ' ', 'b', ' ', 'c', ' ', 'd', ' ', 'e', ' ', ..., ' ', 'm', ' ', 'n', ' ', 'o', ' ', 'p', ' ']
    07:17:12.50 .............................. len(fil_result) = 32
    07:17:12.50  355 |                 for element in result:
    07:17:12.50 ...................... element = 'q'
    07:17:12.50  356 |                     if " " in element:
    07:17:12.50  360 |                         filter(element)
    07:17:12.50 .............................. fil_result = ['a', ' ', 'b', ' ', 'c', ' ', 'd', ' ', 'e', ' ', ..., ' ', 'n', ' ', 'o', ' ', 'p', ' ', 'q', ' ']
    07:17:12.50 .............................. len(fil_result) = 34
    07:17:12.50  355 |                 for element in result:
    07:17:12.50 ...................... element = 'r'
    07:17:12.50  356 |                     if " " in element:
    07:17:12.50  360 |                         filter(element)
    07:17:12.50 .............................. fil_result = ['a', ' ', 'b', ' ', 'c', ' ', 'd', ' ', 'e', ' ', ..., ' ', 'o', ' ', 'p', ' ', 'q', ' ', 'r', ' ']
    07:17:12.50 .............................. len(fil_result) = 36
    07:17:12.50  355 |                 for element in result:
    07:17:12.50 ...................... element = 's'
    07:17:12.50  356 |                     if " " in element:
    07:17:12.50  360 |                         filter(element)
    07:17:12.51 .............................. fil_result = ['a', ' ', 'b', ' ', 'c', ' ', 'd', ' ', 'e', ' ', ..., ' ', 'p', ' ', 'q', ' ', 'r', ' ', 's', ' ']
    07:17:12.51 .............................. len(fil_result) = 38
    07:17:12.51  355 |                 for element in result:
    07:17:12.51 ...................... element = 't'
    07:17:12.51  356 |                     if " " in element:
    07:17:12.51  360 |                         filter(element)
    07:17:12.51 .............................. fil_result = ['a', ' ', 'b', ' ', 'c', ' ', 'd', ' ', 'e', ' ', ..., ' ', 'q', ' ', 'r', ' ', 's', ' ', 't', ' ']
    07:17:12.51 .............................. len(fil_result) = 40
    07:17:12.51  355 |                 for element in result:
    07:17:12.51 ...................... element = 'u'
    07:17:12.51  356 |                     if " " in element:
    07:17:12.51  360 |                         filter(element)
    07:17:12.51 .............................. fil_result = ['a', ' ', 'b', ' ', 'c', ' ', 'd', ' ', 'e', ' ', ..., ' ', 'r', ' ', 's', ' ', 't', ' ', 'u', ' ']
    07:17:12.51 .............................. len(fil_result) = 42
    07:17:12.51  355 |                 for element in result:
    07:17:12.51 ...................... element = 'v'
    07:17:12.51  356 |                     if " " in element:
    07:17:12.51  360 |                         filter(element)
    07:17:12.51 .............................. fil_result = ['a', ' ', 'b', ' ', 'c', ' ', 'd', ' ', 'e', ' ', ..., ' ', 's', ' ', 't', ' ', 'u', ' ', 'v', ' ']
    07:17:12.51 .............................. len(fil_result) = 44
    07:17:12.51  355 |                 for element in result:
    07:17:12.51 ...................... element = 'w'
    07:17:12.51  356 |                     if " " in element:
    07:17:12.51  360 |                         filter(element)
    07:17:12.51 .............................. fil_result = ['a', ' ', 'b', ' ', 'c', ' ', 'd', ' ', 'e', ' ', ..., ' ', 't', ' ', 'u', ' ', 'v', ' ', 'w', ' ']
    07:17:12.51 .............................. len(fil_result) = 46
    07:17:12.51  355 |                 for element in result:
    07:17:12.51 ...................... element = 'x'
    07:17:12.51  356 |                     if " " in element:
    07:17:12.51  360 |                         filter(element)
    07:17:12.51 .............................. fil_result = ['a', ' ', 'b', ' ', 'c', ' ', 'd', ' ', 'e', ' ', ..., ' ', 'u', ' ', 'v', ' ', 'w', ' ', 'x', ' ']
    07:17:12.51 .............................. len(fil_result) = 48
    07:17:12.51  355 |                 for element in result:
    07:17:12.51 ...................... element = 'y'
    07:17:12.51  356 |                     if " " in element:
    07:17:12.51  360 |                         filter(element)
    07:17:12.51 .............................. fil_result = ['a', ' ', 'b', ' ', 'c', ' ', 'd', ' ', 'e', ' ', ..., ' ', 'v', ' ', 'w', ' ', 'x', ' ', 'y', ' ']
    07:17:12.51 .............................. len(fil_result) = 50
    07:17:12.51  355 |                 for element in result:
    07:17:12.51 ...................... element = 'z'
    07:17:12.51  356 |                     if " " in element:
    07:17:12.51  360 |                         filter(element)
    07:17:12.51 .............................. fil_result = ['a', ' ', 'b', ' ', 'c', ' ', 'd', ' ', 'e', ' ', ..., ' ', 'w', ' ', 'x', ' ', 'y', ' ', 'z', ' ']
    07:17:12.51 .............................. len(fil_result) = 52
    07:17:12.51  355 |                 for element in result:
    07:17:12.51  362 |                 fil_result.append("\n\n")
    07:17:12.51 ...................... fil_result = ['a', ' ', 'b', ' ', 'c', ' ', 'd', ' ', 'e', ' ', ..., 'w', ' ', 'x', ' ', 'y', ' ', 'z', ' ', '\n\n']
    07:17:12.51 ...................... len(fil_result) = 53
    07:17:12.51  363 |                 per_picture.append(fil_result)
    07:17:12.53 ...................... per_picture = [['a', ' ', 'b', ..., 'z', ' ', '\n\n'], ['a', ' ', 'b', ..., 'z', ' ', '\n\n']]
    07:17:12.53 ...................... len(per_picture) = 2
    07:17:12.53  364 |                 fil_result = []
    07:17:12.53  349 |         for file_type in images:
    07:17:12.53 .............. file_type = '.jpf'
    07:17:12.53  350 |             if files.endswith(file_type):
    07:17:12.53  349 |         for file_type in images:
    07:17:12.53 .............. file_type = '.jpeg'
    07:17:12.53  350 |             if files.endswith(file_type):
    07:17:12.53  349 |         for file_type in images:
    07:17:12.53 .............. file_type = '.ppm'
    07:17:12.53  350 |             if files.endswith(file_type):
    07:17:12.53  349 |         for file_type in images:
    07:17:12.53  348 |     for files in sourcefiles:
    07:17:12.53 .......... files = 'textfile.txt'
    07:17:12.53  349 |         for file_type in images:
    07:17:12.53 .............. file_type = '.tiff'
    07:17:12.53  350 |             if files.endswith(file_type):
    07:17:12.53  349 |         for file_type in images:
    07:17:12.53 .............. file_type = '.gif'
    07:17:12.53  350 |             if files.endswith(file_type):
    07:17:12.53  349 |         for file_type in images:
    07:17:12.53 .............. file_type = '.png'
    07:17:12.53  350 |             if files.endswith(file_type):
    07:17:12.53  349 |         for file_type in images:
    07:17:12.53 .............. file_type = '.eps'
    07:17:12.53  350 |             if files.endswith(file_type):
    07:17:12.53  349 |         for file_type in images:
    07:17:12.53 .............. file_type = '.bmp'
    07:17:12.53  350 |             if files.endswith(file_type):
    07:17:12.53  349 |         for file_type in images:
    07:17:12.54 .............. file_type = '.jpg'
    07:17:12.54  350 |             if files.endswith(file_type):
    07:17:12.54  349 |         for file_type in images:
    07:17:12.54 .............. file_type = '.jpf'
    07:17:12.54  350 |             if files.endswith(file_type):
    07:17:12.54  349 |         for file_type in images:
    07:17:12.54 .............. file_type = '.jpeg'
    07:17:12.54  350 |             if files.endswith(file_type):
    07:17:12.54  349 |         for file_type in images:
    07:17:12.54 .............. file_type = '.ppm'
    07:17:12.54  350 |             if files.endswith(file_type):
    07:17:12.54  349 |         for file_type in images:
    07:17:12.54  348 |     for files in sourcefiles:
    07:17:12.54 <<< Exit with block in <module>
    [Finished in 1.7s]
    
    opened by DeadBush225 2
  • snoop exist in a for loop after 10 iterations

    snoop exist in a for loop after 10 iterations

    I am using snoop and its very useful

    I have a list variable of 20k items. I just want to see the tracing for few iterations only.

    @snoop
    def mapping(inputlist):
        testing = {}
        for eachDict in inputlist:
            for k, v in eachDict.items():
                testing[k] = v
                # <-------  want to exist snoop after 5 iterations
            # <-------  want to exist snoop after 10 iterations
        return testing
    

    HOw can i achieve the above thing

    opened by syedidiflipt 3
  • Trace recursively, but only my code

    Trace recursively, but only my code

    Hi,

    I would like to trace the http request handling of Django in my development environment.

    But I am sure that the bug is in my code, not in the code of Django.

    I would like to see every line of my code, excluding Django, standard library and other libraries.

    I had a look at the arguments which snoop() accepts, but I think it is not possible up to now.

    Would you accept a PR which implements this?

    Do you have a hint how to implement this?

    opened by guettli 7
  • Add a comparison mode: disable timestamps, obscure 0xblah repr pointers, & canonicalize pathnames

    Add a comparison mode: disable timestamps, obscure 0xblah repr pointers, & canonicalize pathnames

    My first use of snoop was to compare execution logs for a buggy area of the code between two runs to figure out where their behavior diverged. (A weak form of co-execution I suppose)

    But before I could use diff, I had to post process the snoop output to remove the timestamps, obscure the repr's that contain 0x7f267b0a00 style memory addresses, and canonicalize the pathnames in str reprs that contained them as they differed between each execution environment.

    It'd be nice to have a way to do a lot of this upfront via parameters to snoop() itself. I propose both of these:

    • [x] Add the ability to omit timestamps.
    • [ ] Accept a repr post-processing callable.

    The latter would allow for hex pointer value matching and cleanup as well as pathname cleanup. A pointer value cleanup only function could be provided as an example. Beyond that it's probably getting individual use case and application specific as to what people need to sanitize to make execution log comparisons easy.

    opened by gpshead 1
  • Output in HTML format?

    Output in HTML format?

    Hi,

    does snoop support output in HTML format?

    I think this would be really cool: Local variables hidden first, and only if you want to see them you can expand them.

    opened by guettli 1
Owner
Alex Hall
Python metaprogrammer, looking for work
Alex Hall
Debugging manhole for python applications.

Overview docs tests package Manhole is in-process service that will accept unix domain socket connections and present the stacktraces for all threads

Ionel Cristian Mărieș 332 Dec 7, 2022
Cyberbrain: Python debugging, redefined.

Cyberbrain1(电子脑) aims to free programmers from debugging.

laike9m 2.3k Jan 7, 2023
VizTracer is a low-overhead logging/debugging/profiling tool that can trace and visualize your python code execution.

VizTracer is a low-overhead logging/debugging/profiling tool that can trace and visualize your python code execution.

null 2.8k Jan 8, 2023
A package containing a lot of useful utilities for Python developing and debugging.

Vpack A package containing a lot of useful utilities for Python developing and debugging. Features Sigview: press Ctrl+C to print the current stack in

volltin 16 Aug 18, 2022
A toolbar overlay for debugging Flask applications

Flask Debug-toolbar This is a port of the excellent django-debug-toolbar for Flask applications. Installation Installing is simple with pip: $ pip ins

null 863 Dec 29, 2022
Never use print for debugging again

PySnooper - Never use print for debugging again PySnooper is a poor man's debugger. If you've used Bash, it's like set -x for Python, except it's fanc

Ram Rachum 15.5k Jan 1, 2023
Hypothesis debugging with vscode

Hypothesis debugging with vscode

Oliver Mannion 0 Feb 9, 2022
A configurable set of panels that display various debug information about the current request/response.

Django Debug Toolbar The Django Debug Toolbar is a configurable set of panels that display various debug information about the current request/respons

Jazzband 7.3k Dec 31, 2022
A configurable set of panels that display various debug information about the current request/response.

Django Debug Toolbar The Django Debug Toolbar is a configurable set of panels that display various debug information about the current request/respons

Jazzband 7.3k Dec 29, 2022
Python's missing debug print command and other development tools.

python devtools Python's missing debug print command and other development tools. For more information, see documentation. Install Just pip install de

Samuel Colvin 637 Jan 2, 2023
The official code of LM-Debugger, an interactive tool for inspection and intervention in transformer-based language models.

LM-Debugger is an open-source interactive tool for inspection and intervention in transformer-based language models. This repository includes the code

Mor Geva 110 Dec 28, 2022
pdb++, a drop-in replacement for pdb (the Python debugger)

pdb++, a drop-in replacement for pdb What is it? This module is an extension of the pdb module of the standard library. It is meant to be fully compat

null 1k Dec 24, 2022
Full-screen console debugger for Python

PuDB: a console-based visual debugger for Python Its goal is to provide all the niceties of modern GUI-based debuggers in a more lightweight and keybo

Andreas Klöckner 2.6k Jan 1, 2023
Trace any Python program, anywhere!

lptrace lptrace is strace for Python programs. It lets you see in real-time what functions a Python program is running. It's particularly useful to de

Karim Hamidou 687 Nov 20, 2022
Debugger capable of attaching to and injecting code into python processes.

DISCLAIMER: This is not an official google project, this is just something I wrote while at Google. Pyringe What this is Pyringe is a python debugger

Google 1.6k Dec 15, 2022
(OLD REPO) Line-by-line profiling for Python - Current repo ->

line_profiler and kernprof line_profiler is a module for doing line-by-line profiling of functions. kernprof is a convenient script for running either

Robert Kern 3.6k Jan 6, 2023
Monitor Memory usage of Python code

Memory Profiler This is a python module for monitoring memory consumption of a process as well as line-by-line analysis of memory consumption for pyth

Fabian Pedregosa 80 Nov 18, 2022
Sampling profiler for Python programs

py-spy: Sampling profiler for Python programs py-spy is a sampling profiler for Python programs. It lets you visualize what your Python program is spe

Ben Frederickson 9.5k Jan 8, 2023
🔥 Pyflame: A Ptracing Profiler For Python. This project is deprecated and not maintained.

Pyflame: A Ptracing Profiler For Python (This project is deprecated and not maintained.) Pyflame is a high performance profiling tool that generates f

Uber Archive 3k Jan 7, 2023