10

I want to trace the lines of a python script as they are executed. However the programme I use needs to print things to stdout. The trace option to the python trace module prints them to stdout. Is there anwyay to tell it to not print them to stdout, but instead save them to a file? I tried setting the outfile parameter, but it doesn't stop the printing of trace lines.

5 Answers 5

8

You could copy the trace module code, and make a few changes to get it to write its output to a file of your choosing. There are five print statements between lines 600 and 650 that are the ones you want to change. Since you don't need to make it too pretty, you can add this to the very end of the file:

my_out_file = open("/home/mytrace.txt", "w") 

and change the print statements so this:

print "%s(%d): %s" % (bname, lineno, linecache.getline(filename, lineno)), 

becomes this:

print >>my_out_file, "%s(%d): %s" % (bname, lineno, linecache.getline(filename, lineno)), 
Sign up to request clarification or add additional context in comments.

2 Comments

in case this is crashing, you should probably enable line-buffering open(..., buffering=1)
I did exactly what this answer suggested and it worked great. Here's the modified trace script: github.com/bronson/trace.py
3

As per the docs of trace module, the outfile is only used to write updated count information.

Trace module will continue to print the trace information to stdout.

For a manual tracing, if there is an entry function, I have used sys.settrace to do the work of tracing call flows. It can be extended to trace line by line execution. You can always file the information to a file rather than print it to stdout.

A simple structure is

import sys import os import linecache trace_depth = 0 def trace(f): def globaltrace(frame, why, arg): global trace_depth if why == "call": # function call event , extract information ..... pass trace_depth = trace_depth + 1 return None def localtrace(frame, why, arg): global trace_depth if why == "line": # line execution event pass elif why == "return": trace_depth = trace_depth - 1 # function return event return localtrace def _f(*args, **kwds): sys.settrace(globaltrace) result = f(*args, **kwds) sys.settrace(None) return result return _f 

globaltrace and localtrace are callback functions that are called with the event - "why"

say for event when a function is called, you can extract the information from the frame details.

if why == "call": # Parent frame details p_func = frame.f_back.f_code.co_name p_file = frame.f_back.f_code.co_filename p_lineinfo = frame.f_back.f_lineno 

I have posted the full details here.

3 Comments

Is there anyway/other module that can save the trace data to a file?
@Rory: How are you tracing the execution? What commandline are you using? I have used manual tracing before, modifying the output to my taste.
Thank you for your answer. This is a lot of code. Is there a maintained library which could help here?
0

It may happen that you need so-called 'function trace' described for PHP. I created Python tool that produces similar output using mentioned by pyfunc sys.settrace() hook.

Comments

0

Are you invoking trace at the command line? If so, I recommend using the standard method of rerouting any stdout to any file. Redirect all output to file

foo > allout.txt 2>&1 

I'm sure windows has something similar if you're in windows.

1 Comment

I think OP wanted the program's own stdout to still go to the usual place.
0

Another possibility when you're using stdout/stderr for something else is to start a thread to write and feed messages to a queue

import threading from queue import Queue def worker(Q, file_dest): with open(file_dest, "r+", buffering=1) as fh: while True: fh.write(f"{}\n".format(Q.get())) ... dest_file = "some-writeable/path.txt" Q = Queue() # can be a global, but please name it better! t = threading.Thread( worker, args=(Q, dest_file), daemon=True, # don't block exit ) # set t.daemon = True here instead in earlier Python t.start() 

whenever you want to write, use the .put() method

Q.put("some message") 

buffering=1 is used for line-buffering

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.