2

Ok, this is maybe a difficult question. And I don't want you to do all the hard work for me. I'm just tring to get some good advices and points where I should start.

I'm writing a couple of python programs and i'm having a bad time debugging those. So i'd like to create a simple debug function that records a couple of things.

This is how I'd use it:

# Defined in random_function_definitios.py
def some_random_function():
  a = 1 + 1
  debug(a)
  # More stuff

I'd like to display in debug this information:

  • The function that invoked it: some_random_function
  • The filename where that function is defined: random_function_definitios.py
  • The line number: 4
  • Some context: Global variables defined and local variables defined.

I've been taking a look at the inspect module and the frame builtin object. But i'm not completely sure if i'm in the right direction.

Thank you!

santiagobasulto
  • 11,320
  • 11
  • 64
  • 88
  • 1
    Use the debugger. That is what it's for. – Marcin Jun 18 '12 at 19:17
  • Also: http://whathaveyoutried.com/ – Marcin Jun 18 '12 at 19:18
  • I tried a lot with sys._getframe() and inspect.getcurrentframe() – santiagobasulto Jun 18 '12 at 19:18
  • @Lipis Yeah! you can see it that way. I had not noticed that. – santiagobasulto Jun 18 '12 at 19:19
  • @santiagobasulto If you've tried a lot, then show it, and tell us what's wrong with it. You might also find this useful: http://sscce.org/ – Marcin Jun 18 '12 at 19:20
  • Look at code introspection on [this other SO question](http://stackoverflow.com/questions/4014722/viewing-the-code-of-a-python-function) – inspectorG4dget Jun 18 '12 at 19:27
  • 1
    @santiagobasulto If you have some of that done, it should be in your question. – Marcin Jun 18 '12 at 19:34
  • 1
    @santiagobasulto show me what you have – Jakob Bowyer Jun 18 '12 at 19:35
  • Thank you guys. I really needed this. I hate when you do it. Why don't you leave people alone to get help. Isn't a real question to ask how to get a file name of an invokation? Isn't a real question of how to get global variables? You're not doing any good to this community. – santiagobasulto Jun 18 '12 at 19:39
  • @santiagobasulto Right now, your question amounts to "write me some code, and not the code I've already thought of, but won't show to you". Show the code you have, explain how it doesn't meet your needs, and what aspects of the task confuse you, or you otherwise need help with. – Marcin Jun 18 '12 at 21:08
  • @Marcin Wouldn't be nicer to say this before? And also, what if I don't have any code? What if i'm a beginner with no knowldege of Reflection? I do have some code, and will edit my question in a moment. I really need this. And I was looking for help. – santiagobasulto Jun 18 '12 at 21:22
  • @santiagobasulto Read the comments I have posted. I have said this at least twice. In any case, I shouldn't need to warn you not to complain about good faith attempts to answer your question with reasonable content. – Marcin Jun 18 '12 at 21:23

2 Answers2

2

You can use Python's standard logging facilities. Plenty of data come with a log record - full list of them is available in the documentation: http://docs.python.org/library/logging.html#logrecord-attributes . Ones you need are funcName, filename, lineno . To have dump of local variables logged you can convert to string output of built-in function locals() and use it as a log message. All you need do is user a logger like:

import logging

logger = logging.getLogger('some_module')

def some_random_function():
    a = 1 + 1
    logger.debug(str(locals()))

And configure it with proper format using previously mentioned formatting attributes. All of this is well-documented in Basic Logging Tutorial: http://docs.python.org/howto/logging.html#logging-basic-tutorial

edit

But if I were you I would just start python debugger in the debugged context to check all you wanna check interactively:

def some_random_function():
    a = 1 + 1
    import pdb; pdb.set_trace()
  • I already know this. Thank you, but it's not useful. Actually, i'm taking a look at the logging module source code. – santiagobasulto Jun 18 '12 at 19:24
  • @santiagobasulto This is a valid answer to your question. It's certainly not Mikolaj's fault that your question is very broad, and that you don't show any approaches you have rejected. – Marcin Jun 18 '12 at 19:26
  • Also, If you take a look at @user1288054 answer you see he replied exactly what I need. – santiagobasulto Jun 18 '12 at 19:32
  • 2
    @santiagobasulto Unless you're paying for help, don't complain about the help you get. – Marcin Jun 18 '12 at 19:33
  • I'm not complaining. I said thanks. Also I think Mkilaj answer can be useful to somebody else. I just pointed out that this is not what i look for. Anyway, i don't know what are you doing here if you're just doing bad comments instead of try to help us (it seems that there are more people than me interesting in this topic). – santiagobasulto Jun 18 '12 at 19:37
2

I wrote my own debugger.py with info / warning and debug messages.

see: https://github.com/unixunion/toolbox/blob/master/python/debugger.py

I also use a traceback to go through the stack like:

except Exception, e:
    # capture the traceback data
    exc_type, exc_value, exc_traceback = sys.exc_info()
    warningMsg("-14 %s" % str(e))
    warningMsg("Exec Traceback")
    traceback.print_tb(exc_traceback, limit=1, file=sys.stdout)
    warningMsg("Exception")
    traceback.print_exception(exc_type, exc_value, exc_traceback, limit=2, file=sys.stdout)
    raise

Gives results like:

WARNING fabfile.py:76 glassfish_deploy()-14 cannot concatenate 'str' and 'float' objects
WARNING fabfile.py:77 glassfish_deploy()Exec Traceback
File "/home/marzubus/go-agent-scripts/fabfile.py", line 52, in glassfish_deploy    oiled =     gfOil(**kwargs)
WARNING fabfile.py:79 glassfish_deploy()Exception
Traceback (most recent call last):  File "/home/marzubus/go-agent-scripts/fabfile.py",    line 52, in glassfish_deploy
oiled = gfOil(**kwargs)
File "/home/marzubus/go-agent-scripts/oilon/gfdeployer.py", line 37, in __init__
self.tmpDirectory = '/tmp/' + self.domainName + self.time
TypeError: cannot concatenate 'str' and 'float' objects

Kegan

unixunion
  • 385
  • 2
  • 4
  • 13
  • 1
    Please learn about the markup facilities on SO. I won't edit your answer, so you have the chance to do so (look at the buttons at the top of the edit box). – Marcin Jun 18 '12 at 19:27