cool-RR / PySnooper

Never use print for debugging again
MIT License
16.38k stars 952 forks source link

output to logging handle #190

Closed MstWntd closed 4 years ago

MstWntd commented 4 years ago

Hi,

This tool is awesome, I have two questions tho:

1) How can I enable/disable the logging programmatically 2) How can I ensure all the log output goes to logging module as WARN or DEBUG?

Thank you.

cool-RR commented 4 years ago

Thank you :)

Does setting the environment variable PYSNOOPER_DISABLED=1 solve your problem, or would a Python call be better?

How about @snoop(logger.warn)?

MstWntd commented 4 years ago

That works nicely, also I was hoping for a Python call which I can then control with a switch passed via argsparse.

to give some context, almost all of the tools I write are frozen, as a result the source code is not packaged, the result is just binary, which you cant do much debugging on.. and having this level of printing with minimal to no effort is a blessing!

cool-RR commented 4 years ago

I understand. I think I'll keep it as an environment variable for now. Thanks for the feedback!

alexmojaki commented 4 years ago

You can set the environment variable within Python, but you have to do it before importing snoop.

You can patch pysnooper.tracer.DISABLED, but you have to do it before functions are decorated.

Alternatively you can use my fork https://github.com/alexmojaki/snoop and snoop.install(enabled=False) which can be called at any time.

So when you're debugging, does it show lots of SOURCE IS UNAVAILABLE? Isn't that annoying?

cool-RR commented 4 years ago

Alex, if you like crazy features, we could always run uncompyle6 on-demand and get an approximation for the source :)

alexmojaki commented 4 years ago

I was literally just looking into that, mostly out of curiosity. But it turns out uncompyle6 is not good enough to produce source that has the right line numbers. For example this:

import inspect
import io

import uncompyle6.main

code = inspect.currentframe().f_code
out = io.StringIO()
uncompyle6.main.decompile(None, code, out=out)
decompiled = out.getvalue()
compiled = compile(decompiled, "", "exec")

print("Matching attrs:")
for key in dir(code):
    if not key.startswith("co_"):
        continue
    print(key, getattr(compiled, key) == getattr(code, key))

print("\nDecompiled source:\n")
print(decompiled)

outputs:

Matching attrs:
co_argcount True
co_cellvars True
co_code True
co_consts True
co_filename False
co_firstlineno False
co_flags True
co_freevars True
co_kwonlyargcount True
co_lnotab False
co_name True
co_names True
co_nlocals True
co_posonlyargcount True
co_stacksize True
co_varnames True

Decompiled source:

# uncompyle6 version 3.7.0
# Python bytecode 3.8
# Decompiled from: Python 3.8.0 (default, Oct 30 2019, 12:16:01) 
# [GCC 7.4.0]
# Embedded file name: /home/alex/.config/JetBrains/PyCharm2020.1/scratches/scratch_697.py
import inspect, io, uncompyle6.main
code = inspect.currentframe().f_code
out = io.StringIO()
uncompyle6.main.decompile(None, code, out=out)
decompiled = out.getvalue()
compiled = compile(decompiled, '', 'exec')
print('Matching attrs:')
for key in dir(code):
    if not key.startswith('co_'):
        pass
    else:
        print(key, getattr(compiled, key) == getattr(code, key))

print('\nDecompiled source:\n')
print(decompiled)
cool-RR commented 4 years ago

Great minds think alike, sometimes a few years in advance :) https://github.com/rocky/python-uncompyle6/issues/133