strace a python function

user19087 picture user19087 · Apr 28, 2016 · Viewed 7.4k times · Source

Is it possible to strace a python function for opened files, and differentiate if they were opened by python or a subprocess?

read_python, read_external = [], []

@strace_read(read_python, read_external)
function test():
    file = open("foo.txt", "r")
    subprocess.call(["cat", "bar.txt"])

for file in read_python:
    print("python:      ", file)
for file in read_external:
    print("external:    ", file)

So the output is as:

>>> python:      foo.txt
>>> external:    bar.txt

I'm most interested in using a decorator. Differentiating isn't a priority.

Conceptually, my best guess is to replace instances of load_function(open) with wrappers ... actually, I have no idea, there are too many ways to access open.

Answer

viraptor picture viraptor · Apr 28, 2016

I'd solve it in a much simpler way but with similar result. Instead of figuring out how to enable strace on a single function:

  1. Create decorator like this: (untested)

-

def strace_mark(f):
    def wrapper(*args, **kwargs):
        try:
            open('function-%s-start' % f.__name__, 'r')
        except:
            pass
        ret = f(*args, **kwargs)
        try:
            open('function-%s-end' % f.__name__, 'r')
        except:
            pass
        return ret
  1. Run the whole app under strace -e file.
  2. Get only the parts between calls open(function-something-start) and open(function-something-end).

If you do strace -f, you get the python/external separation for free. Just look at what pid calls the function.