saving cProfile results to readable external file saving cProfile results to readable external file python python

saving cProfile results to readable external file


Updated. You can get output of profiler using io.StringIO() and save it into file.Here is an example:

import cProfileimport pstatsimport iodef my_func():    result = []    for i in range(10000):        result.append(i)    return resultpr = cProfile.Profile()pr.enable()my_result = my_func()pr.disable()s = io.StringIO()ps = pstats.Stats(pr, stream=s).sort_stats('tottime')ps.print_stats()with open('test.txt', 'w+') as f:    f.write(s.getvalue())

Run our script and open test.txt. You will see readable result:

   10002 function calls in 0.003 seconds   Ordered by: internal time   ncalls  tottime  percall  cumtime  percall filename:lineno(function)        1    0.002    0.002    0.003    0.003 /path_to_script.py:26(my_func)    10000    0.001    0.000    0.001    0.000 {method 'append' of 'list' objects}        1    0.000    0.000    0.000    0.000 {method 'disable' of '_lsprof.Profiler' objects}

Also I can recommend to use dump_stats + pstats.Stats. Here is an example how to use it. Structure of files:

# test_ex.py - just a small web appimport cProfileimport jsonfrom functools import wrapsfrom flask import Flaskfrom example.mod1 import func1from example.mod2 import func2app = Flask(__name__)# profiling decoratordef profiling():    def _profiling(f):        @wraps(f)        def __profiling(*rgs, **kwargs):            pr = cProfile.Profile()            pr.enable()            result = f(*rgs, **kwargs)            pr.disable()            # save stats into file            pr.dump_stats('profile_dump')            return result        return __profiling    return _profiling# demonstration route with profiler@app.route('/test')@profiling()def test():    counter = func1()    dict_data = func2()    result = dict()    for key, val in dict_data.items():        result[key] = val + counter    return json.dumps(result)if __name__ == '__main__':    app.run(debug=True, port=8083)

example package - let's imagine that this is some kind of application logic.

# example.mod1def func1():    counter = 0    for i in range(100000):        counter += i    return counter# example.mod2def func2():    res = dict()    for i in range(300000):        res['key_' + str(i)] = i    return res

Now let's run server(python3 test_ex.py) and open http://localhost:8083/test. After a few seconds you will see long json. After that you will see profile_dump file in project folder. Now run python live interpreter in project folder and print our dump using pstats:

import pstatsp = pstats.Stats('profile_dump')# skip strip_dirs() if you want to see full path'sp.strip_dirs().print_stats()

stats

Also you can easy sorting results:

p.strip_dirs().sort_stats('tottime').print_stats()p.strip_dirs().sort_stats('cumulative').print_stats()p.strip_dirs().sort_stats().print_stats('mod1')

Hope this helps.


You don't really need StringIO, as a file qualifies as a stream.

import pstatswith open("profilingStatsAsText.txt", "w") as f:    ps = pstats.Stats("profilingResults.cprof", stream=f)    ps.sort_stats('cumulative')    ps.print_stats()


Expanding upon the previous answer, you can dump everything out to a .csv file to sort and play around with in your favorite spreadsheet application.

import pstats,StringIO# print stats to a stringresult=StringIO.StringIO()pstats.Stats(filename,stream=result).print_stats()result=result.getvalue()# chop the string into a csv-like bufferresult='ncalls'+result.split('ncalls')[-1]result='\n'.join([','.join(line.rstrip().split(None,6)) for line in result.split('\n')])# save it to diskf=open(filename.rsplit('.')[0]+'.csv','w')f.write(result)f.close()