将 cProfile 结果保存到可读的外部文件
saving cProfile results to readable external file
我正在使用 cProfile
尝试分析我的代码:
pr = cProfile.Profile()
pr.enable()
my_func() # the code I want to profile
pr.disable()
pr.print_stats()
但是结果太长,无法在Spyder终端完整显示(看不到运行耗时最长的函数调用...)。我还尝试使用
保存结果
cProfile.run('my_func()','profile_results')
但输出文件不是人类可读的格式(尝试使用和不使用 .txt
后缀)。
所以我的问题是如何将分析结果保存到人类可读的外部文件中(例如以 .txt
格式正确显示所有单词)?
已更新。 您可以使用 io.StringIO() 获取探查器的输出并将其保存到文件中。
这是一个例子:
import cProfile
import pstats
import io
def my_func():
result = []
for i in range(10000):
result.append(i)
return result
pr = 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())
运行 我们的脚本并打开 test.txt
。您将看到可读的结果:
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}
我也可以推荐使用dump_stats + pstats.Stats。这是一个如何使用它的例子。文件结构:
# test_ex.py - just a small web app
import cProfile
import json
from functools import wraps
from flask import Flask
from example.mod1 import func1
from example.mod2 import func2
app = Flask(__name__)
# profiling decorator
def 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 包 - 让我们想象这是某种应用程序逻辑。
# example.mod1
def func1():
counter = 0
for i in range(100000):
counter += i
return counter
# example.mod2
def func2():
res = dict()
for i in range(300000):
res['key_' + str(i)] = i
return res
现在让我们 运行 服务器(python3 test_ex.py
)并打开 http://localhost:8083/test
。几秒钟后你会看到很长的json。之后您将在项目文件夹中看到 profile_dump 文件。现在 运行 python 项目文件夹中的实时解释器并使用 pstats:
打印我们的转储
import pstats
p = pstats.Stats('profile_dump')
# skip strip_dirs() if you want to see full path's
p.strip_dirs().print_stats()
您还可以轻松排序结果:
p.strip_dirs().sort_stats('tottime').print_stats()
p.strip_dirs().sort_stats('cumulative').print_stats()
p.strip_dirs().sort_stats().print_stats('mod1')
希望这对您有所帮助。
扩展上一个答案,您可以将所有内容转储到一个 .csv 文件中,以便在您最喜欢的电子表格应用程序中进行排序和使用。
import pstats,StringIO
# print stats to a string
result=StringIO.StringIO()
pstats.Stats(filename,stream=result).print_stats()
result=result.getvalue()
# chop the string into a csv-like buffer
result='ncalls'+result.split('ncalls')[-1]
result='\n'.join([','.join(line.rstrip().split(None,6)) for line in result.split('\n')])
# save it to disk
f=open(filename.rsplit('.')[0]+'.csv','w')
f.write(result)
f.close()
您实际上并不需要 StringIO,因为文件符合流的条件。
import pstats
with open("profilingStatsAsText.txt", "w") as f:
ps = pstats.Stats("profilingResults.cprof", stream=f)
ps.sort_stats('cumulative')
ps.print_stats()
您可以使用 dump_stats。在 Python 3.10:
with cProfile.Profile() as pr:
my_func()
pr.dump_stats('/path/to/filename.prof')
您可以 运行 探查器将输出保存到一个文件中,正如您所做的那样:
import cProfile
cProfile.run('my_func()', 'profile_results')
然后使用 class pstats.Stats
(https://docs.python.org/3/library/profile.html#the-stats-class):
格式化结果
import pstats
file = open('formatted_profile.txt', 'w')
profile = pstats.Stats('.\profile_results', stream=file)
profile.sort_stats('cumulative') # Sorts the result according to the supplied criteria
profile.print_stats(15) # Prints the first 15 lines of the sorted report
file.close()
我正在使用 cProfile
尝试分析我的代码:
pr = cProfile.Profile()
pr.enable()
my_func() # the code I want to profile
pr.disable()
pr.print_stats()
但是结果太长,无法在Spyder终端完整显示(看不到运行耗时最长的函数调用...)。我还尝试使用
保存结果 cProfile.run('my_func()','profile_results')
但输出文件不是人类可读的格式(尝试使用和不使用 .txt
后缀)。
所以我的问题是如何将分析结果保存到人类可读的外部文件中(例如以 .txt
格式正确显示所有单词)?
已更新。 您可以使用 io.StringIO() 获取探查器的输出并将其保存到文件中。 这是一个例子:
import cProfile
import pstats
import io
def my_func():
result = []
for i in range(10000):
result.append(i)
return result
pr = 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())
运行 我们的脚本并打开 test.txt
。您将看到可读的结果:
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}
我也可以推荐使用dump_stats + pstats.Stats。这是一个如何使用它的例子。文件结构:
# test_ex.py - just a small web app
import cProfile
import json
from functools import wraps
from flask import Flask
from example.mod1 import func1
from example.mod2 import func2
app = Flask(__name__)
# profiling decorator
def 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 包 - 让我们想象这是某种应用程序逻辑。
# example.mod1
def func1():
counter = 0
for i in range(100000):
counter += i
return counter
# example.mod2
def func2():
res = dict()
for i in range(300000):
res['key_' + str(i)] = i
return res
现在让我们 运行 服务器(python3 test_ex.py
)并打开 http://localhost:8083/test
。几秒钟后你会看到很长的json。之后您将在项目文件夹中看到 profile_dump 文件。现在 运行 python 项目文件夹中的实时解释器并使用 pstats:
import pstats
p = pstats.Stats('profile_dump')
# skip strip_dirs() if you want to see full path's
p.strip_dirs().print_stats()
您还可以轻松排序结果:
p.strip_dirs().sort_stats('tottime').print_stats()
p.strip_dirs().sort_stats('cumulative').print_stats()
p.strip_dirs().sort_stats().print_stats('mod1')
希望这对您有所帮助。
扩展上一个答案,您可以将所有内容转储到一个 .csv 文件中,以便在您最喜欢的电子表格应用程序中进行排序和使用。
import pstats,StringIO
# print stats to a string
result=StringIO.StringIO()
pstats.Stats(filename,stream=result).print_stats()
result=result.getvalue()
# chop the string into a csv-like buffer
result='ncalls'+result.split('ncalls')[-1]
result='\n'.join([','.join(line.rstrip().split(None,6)) for line in result.split('\n')])
# save it to disk
f=open(filename.rsplit('.')[0]+'.csv','w')
f.write(result)
f.close()
您实际上并不需要 StringIO,因为文件符合流的条件。
import pstats
with open("profilingStatsAsText.txt", "w") as f:
ps = pstats.Stats("profilingResults.cprof", stream=f)
ps.sort_stats('cumulative')
ps.print_stats()
您可以使用 dump_stats。在 Python 3.10:
with cProfile.Profile() as pr:
my_func()
pr.dump_stats('/path/to/filename.prof')
您可以 运行 探查器将输出保存到一个文件中,正如您所做的那样:
import cProfile
cProfile.run('my_func()', 'profile_results')
然后使用 class pstats.Stats
(https://docs.python.org/3/library/profile.html#the-stats-class):
import pstats
file = open('formatted_profile.txt', 'w')
profile = pstats.Stats('.\profile_results', stream=file)
profile.sort_stats('cumulative') # Sorts the result according to the supplied criteria
profile.print_stats(15) # Prints the first 15 lines of the sorted report
file.close()