J'utilise cProfile
essayez de profiler mes codes:
pr = cProfile.Profile()
pr.enable()
my_func() # the code I want to profile
pr.disable()
pr.print_stats()
Cependant, les résultats sont trop longs et ne peuvent pas être entièrement affichés dans le terminal Spyder (les appels de fonction qui prennent le plus de temps à s'exécuter ne sont pas visibles ...). J'ai également essayé d'enregistrer les résultats en utilisant
cProfile.run('my_func()','profile_results')
mais le fichier de sortie n'est pas au format lisible par l'homme (essayé avec et sans .txt
suffixe).
Ma question est donc de savoir comment enregistrer les résultats du profilage dans un fichier externe qui est lisible par l'homme (comme dans un .txt
format avec tous les mots correctement affichés)?
Mise à jour. Vous pouvez obtenir la sortie du profileur en utilisant io.StringIO () et l'enregistrer dans un fichier. Voici un exemple:
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())
Exécutez notre script et ouvrez test.txt
. Vous verrez un résultat lisible:
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}
Je peux également recommander d'utiliser dump_stats + pstats.Stats . Voici un exemple d'utilisation. Structure des fichiers:
# 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)
exemple de package - imaginons qu'il s'agit d'une sorte de logique d'application.
# 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
Maintenant, exécutons le serveur (python3 test_ex.py
) et ouvrez http://localhost:8083/test
. Après quelques secondes, vous verrez un long json. Après cela, vous verrez le fichier profile_dump dans le dossier du projet. Maintenant, exécutez python live interpreter dans le dossier du projet et imprimez notre vidage en utilisant pstats :
import pstats
p = pstats.Stats('profile_dump')
# skip strip_dirs() if you want to see full path's
p.strip_dirs().print_stats()
Vous pouvez également trier facilement les résultats:
p.strip_dirs().sort_stats('tottime').print_stats()
p.strip_dirs().sort_stats('cumulative').print_stats()
p.strip_dirs().sort_stats().print_stats('mod1')
J'espère que cela t'aides.
Vous n'avez pas vraiment besoin de StringIO, car un fichier est considéré comme un flux.
import pstats
with open("profilingStatsAsText.txt", "w") as f:
ps = pstats.Stats("profilingResults.cprof", stream=f)
ps.sort_stats('cumulative')
ps.print_stats()
En développant la réponse précédente, vous pouvez tout vider dans un fichier .csv pour trier et jouer avec dans votre application de feuille de calcul préférée.
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()
vous pouvez utiliser dump_stats . Dans Python 3.8:
with cProfile.Profile() as pr:
my_func()
pr.dump_stats('/path/to/filename.prof')