alexmojaki / snoop

A powerful set of Python debugging tools, based on PySnooper
MIT License
1.28k stars 35 forks source link

Trace recursively, but only my code #51

Open guettli opened 2 years ago

guettli commented 2 years ago

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?

alexmojaki commented 2 years ago

Here's an example of how you can 'blacklist' folders from tracing:

import inspect
import os.path

import snoop.tracer

# Paths starting with any value in internal_directories are ignored when tracing
snoop.tracer.internal_directories += (
    # Avoid tracing anything in the standard library
    os.path.dirname(inspect.__file__),
)

@snoop(depth=5)
def foo():
    # This line would normally get traced
    source = inspect.getsource(foo)
    # Inner function to show that depth is still working
    return bar(source)

def bar(s):
    return s * 2

foo()
guettli commented 2 years ago

I think I have a special case which does not work. I start to snoop in a code which should get skipped.

Example:

# base.py

from sub.start import start

def method():
    print('here')
start(method)
# sub/start.py
import inspect
import os.path

import snoop.tracer

# Paths starting with any value in internal_directories are ignored when tracing
snoop.tracer.internal_directories += (
    # Avoid tracing anything in the standard library
    os.path.dirname(inspect.__file__),

    # Avoid tracing file in the sub-directory.
    os.path.dirname(__file__),
)

@snoop(depth=5)
def start(method):
    method()

output

(snoop-env) guettli@p15:~/tmp/snoop-env$ python base.py 
22:04:37.79 >>> Call to start in File "/home/guettli/tmp/snoop-env/sub/start.py", line 16
22:04:37.79 ...... method = <function method at 0x7fccc53421f0>
22:04:37.79   16 | def start(method):
22:04:37.79   17 |     method()
here
22:04:37.79 <<< Return value from start: None

I would like to see the print('here'). But it does not get traced.


Above example is just to have something which can be reproduced.

In my real use case I want to start snooping in BaseHandler.get_response() of Django.

But I don't want to trace Django, I just want to trace my code.

yantaozhao commented 2 years ago

I think there's a bug in snoop, my case is that the print('here') was traced, but "here" was not output to the console at all. My workaround is to use print("here", file=sys.stderr) because internally snoop use stderr as output sink by default.

alexmojaki commented 2 years ago

Hi @yantaozhao. This sounds unrelated to the rest of this issue, you should probably open a new one.

In any case, I can't see how what you're describing could be a bug in snoop. snoop doesn't control what print does. Just because snoop is using stderr, doesn't mean that everything else has to. It sounds like the environment in which you're running your code is showing stderr but not stdout for some reason.

rkpagadala commented 2 years ago

@alexmojaki How does snoop.tracer work with snoop.Config? I want multiple configurations and possibly distinct dont trace directories for each of the config.

alexmojaki commented 2 years ago

snoop.tracer is a module, while snoop.Config is a class. snoop.tracer.internal_directories is global. To do what you're saying, you'll need to override snoop.tracer.Tracer._is_internal_frame.

rkpagadala commented 2 years ago

@alexmojaki First. Thanks for the snoop and birdseye. Second thanks for the quick response.

ChillarAnand commented 1 year ago

Here's an example of how you can 'blacklist' folders from tracing:

import inspect
import os.path

import snoop.tracer

# Paths starting with any value in internal_directories are ignored when tracing
snoop.tracer.internal_directories += (
    # Avoid tracing anything in the standard library
    os.path.dirname(inspect.__file__),
)

@snoop(depth=5)
def foo():
    # This line would normally get traced
    source = inspect.getsource(foo)
    # Inner function to show that depth is still working
    return bar(source)

def bar(s):
    return s * 2

foo()

Thanks for sharing a working example on blacklisting the directories.

Most of the time, users need a simple flag to blacklist python standard library as well as third party packages that are installed. If snoop can provide the flags, it would be great.

00sapo commented 7 months ago

Most of the time, users need a simple flag to blacklist python standard library as well as third party packages that are installed. If snoop can provide the flags, it would be great.

That's as easy as a one-liner:


from pathlib import Path
import snoop

snoop.tracer.internal_directories += tuple(
    map(str, Path(snoop.tracer.internal_directories[0]).parent.glob("*"))
)