Understanding some python internals
Michael Hudson
mwh at python.net
Tue Nov 12 09:32:49 EST 2002
gerson.kurz at t-online.de (Gerson Kurz) writes:
> I'm trying to understand how the python debugger package works.
Ah.
> To that effect, I've written a kind of "strace for python", that
> should tell me each instruction as it happens, in a tracefile.
>
> The code basically does this:
>
> - use sys.settrace() to attach a tracefunc to every statement executed
> - try to analyze the arguments passed to the tracefunc
>
> So far, so good. Preliminary results can be seen here:
>
> http://p-nand-q.com/python/strace.zip
>
> The test code I want to analyze is this:
>
> ------------------------
> test = 60
>
> def test(x):
> return x*2
>
> i = 0
> while i < 5:
> print test(i)
> i += 1
>
> exec("test(42)")
> ------------------------
>
> Nothing too deviant, right? Try to run strace.py over this, and look
> into the result (STRACE.LOG).
>
> Ok, my questions:
>
> (1) I want to disassemble the current step that the tracefunc is
> called for - nothing else.
So you want to print the instruction that gets executed next?
> dis.disassemble takes a code object, but will disassemble the
> *whole* code object, not just some part. (Same, if I pass it frame
> rather than code). How can I do that?
Well, you can't *use* dis (I think). You can probably crib the code
you need from that module, though.
> I would guess that it has something to do with the members
> frame.f_code.co_code and co_lnotab - the "documentation" says the
> latter is "encoded mapping of line numbers to bytecode indices", can
> somebody enlighten me on that?
f_code & f_lasti should be all you need. You don't really want to try
to understand co_lnotab, but if you do, grep for it in
Python/compile.c. There are some comments that explain how it works.
> (2) I want to print the source for the current step that the tracefunc
> is called for - nothing else. My first attempt (which is in the
> current source) is to read the file from frame.f_code.co_filename and
> read the line that is given in frame.f_lineno). This has two problems:
>
> a) if the source spans more than one line, only the first line will be
> shown
Yup. Not much that can be done about that, I think. It might be the
last line in some circumstances, too...
> b) if the source is in an exec() statement, co_filename is "<string>".
> (See also question (3))
Well, in this case the source may have gone to the big bitbucket in
the sky.
> Is there are a "canonic" way of getting the code about to be executed
> inside a tracefunc?
No. See above. The inspect module may help...
> I tried inspect.getsource(frame) - but that prints the source for the
> whole code object, not the current frame. Bug or intended behaviour?
Oh :) Don't understand the distinction here? If you mean you get the
code for the whole function rather than just for the currently
executing line, then surely that's the intended behaviour -- as that's
what it does.
> (3) If the code object is in an exec statement, co_filename is
> "<string>" and as far as I can see the code executed cannot be read
> from inside the tracefunc. Or can it?
No. See above.
Cheers,
M.
--
"Sturgeon's Law (90% of everything is crap) applies to Usenet."
"Nothing guarantees that the 10% isn't crap, too."
-- Gene Spafford's Axiom #2 of Usenet, and a corollary
More information about the Python-list
mailing list