Есть ли какой-нибудь простой способ проверить скрипт python?
Обычно я использую командное time
оболочки . Моя цель-проверить, являются ли данные небольшим, средним, большим или очень большим набором, сколько времени и памяти будет использоваться.
Есть инструменты для linux или просто python, чтобы сделать это?
Ответы - Есть ли какой-нибудь простой способ проверить скрипт python? / Is there any simple way to benchmark python script?

20.10.2009 11:45:04
Взгляните на timeit, профилировщик python и pycallgraph . Также не забудьте взглянуть на комментарий ниже nikicc
упоминающий "SnakeViz". Это дает вам еще одну визуализацию данных профилирования, которая может быть полезной.
раз все
def test():
"""Stupid test function"""
lst = []
for i in range(100):
lst.append(i)
if __name__ == '__main__':
import timeit
print(timeit.timeit("test()", setup="from __main__ import test"))
По сути, вы можете передать ему код python в виде строкового параметра,и он будет выполняться в указанное количество раз и выводит время выполнения. Важные биты из документов:
timeit.timeit(stmt='pass', setup='pass', timer=<default timer>, number=1000000)
Создайте экземпляр
Timer
с заданной инструкцией, setup функция кода и таймера и запустить ееtimeit
Номер времени выполнения основного утверждения. При этом выполняется настройка оператор один раз, а затем возвращает время, необходимое для выполнения основного утверждение несколько раз, измеряется в секундах как поплавок. Аргумент - это число раз, прошедших через цикл, по умолчанию равное единице. миллион. Главная инструкция, инструкция установки и функция таймера подлежащие использованию передаются конструктору.
Примечание
По умолчанию
Timer.timeit(number=1000000)
временно отключаетtimeit
во время хронометража. Преимущество такого подхода заключается в том, что это делает независимые тайминги более сопоставимыми. Этот недостаток является что GC может быть важным компонентом работы измеряемая функция. Если это так, то GC может быть повторно включен в качестве первого оператор в строке настройки. Например:
garbage collection
Профилирование
Профилирование даст вам гораздо более детальное представление о том, что происходит. Вот "мгновенный пример" из официальных документов:
timeit.Timer('for i in xrange(10): oct(i)', 'gc.enable()').timeit()
Что даст вам:
import cProfile import re cProfile.run('re.compile("foo|bar")')
Оба этих модуля должны дать вам представление о том, где искать узкие места.
Также, чтобы разобраться с выводом
197 function calls (192 primitive calls) in 0.002 seconds Ordered by: standard name ncalls tottime percall cumtime percall filename:lineno(function) 1 0.000 0.000 0.001 0.001 <string>:1(<module>) 1 0.000 0.000 0.001 0.001 re.py:212(compile) 1 0.000 0.000 0.001 0.001 re.py:268(_compile) 1 0.000 0.000 0.000 0.000 sre_compile.py:172(_compile_charset) 1 0.000 0.000 0.000 0.000 sre_compile.py:201(_optimize_charset) 4 0.000 0.000 0.000 0.000 sre_compile.py:25(_identityfunction) 3/1 0.000 0.000 0.000 0.000 sre_compile.py:33(_compile)
, загляните в этот постпикаллграф
Этот модуль использует graphviz для создания callgraphs, таких как:
Вы можете легко увидеть, какие пути использовали больше всего времени по цвету. Вы можете либо создать их с помощью PYCALLGRAPH API, либо с помощью упакованного сценария:
profile
Хотя накладные расходы довольно значительны. Поэтому для уже давно запущенных процессов создание графика может занять некоторое время.

python -m cProfile -o results.prof myscript.py
. файл oputput затем может быть очень красиво представлен в браузере программой под названием SnakeViz с использованием snakeviz results.prof


20.10.2009 12:38:42
Взгляните на нос и на один из его плагинов, этот в частности.
После установки nose-это скрипт в вашем пути, и вы можете вызвать его в каталоге, который содержит некоторые скрипты python:
$: nosetests
Это будет выглядеть во всех файлах python в текущем каталоге и выполнит любую функцию, которую он распознает как тест: например, он распознает любую функцию со словом test_ в ее имени как тест.
Так что вы можете просто создать скрипт python под названием test_yourfunction.py и напишите в нем что-нибудь вроде этого:
$: cat > test_yourfunction.py
def test_smallinput():
yourfunction(smallinput)
def test_mediuminput():
yourfunction(mediuminput)
def test_largeinput():
yourfunction(largeinput)
Тогда тебе придется бежать.
$: nosetest --with-profile --profile-stats-file yourstatsprofile.prof testyourfunction.py
и чтобы прочитать файл профиля, используйте эту строку python:
python -c "import hotshot.stats ; stats = hotshot.stats.load('yourstatsprofile.prof') ; stats.sort_stats('time', 'calls') ; stats.print_stats(200)"

nose
полагается на хотшота. Он больше не поддерживается начиная с Python 2.5 и хранится только " для специализированного использования"


05.04.2011 01:47:21
Обычно я быстро time ./script.py
чтобы посмотреть, сколько времени это займет. Это не показывает вам память, хотя, по крайней мере, не по умолчанию. Вы можете использовать /usr/bin/time -v ./script.py
чтобы получить много информации, включая использование памяти.

/usr/bin/time
with-v
опция недоступна по умолчанию во многих дистрибутивах, должна быть установлена. sudo apt-get install time
в debian, ubuntu и др. pacman -S time
archlinux

22.06.2012 10:46:52
Я использую простой декоратор, чтобы время func
def st_time(func):
"""
st decorator to calculate the total time of a func
"""
def st_func(*args, **keyArgs):
t1 = time.time()
r = func(*args, **keyArgs)
t2 = time.time()
print "Function=%s, Time=%s" % (func.__name__, t2 - t1)
return r
return st_func


08.08.2012 08:55:00
Модуль timeit
был медленным и странным, поэтому я написал это:
def timereps(reps, func):
from time import time
start = time()
for i in range(0, reps):
func()
end = time()
return (end - start) / reps
Пример:
import os
listdir_time = timereps(10000, lambda: os.listdir('/'))
print "python can do %d os.listdir('/') per second" % (1 / listdir_time)
Для меня это говорит::
python can do 40925 os.listdir('/') per second
Это примитивный вид бенчмаркинга, но он достаточно хорош.


22.06.2017 10:27:29
Профилировщик памяти для всех ваших потребностей в памяти.
https://pypi.python.org/pypi/memory_profiler
Выполнить пункт Установить:
pip install memory_profiler
Импорт библиотеки:
import memory_profiler
Добавьте декоратора к элементу, который вы хотите профилировать:
@profile
def my_func():
a = [1] * (10 ** 6)
b = [2] * (2 * 10 ** 7)
del b
return a
if __name__ == '__main__':
my_func()
Выполните код:
python -m memory_profiler example.py
Получите результат:
Line # Mem usage Increment Line Contents
==============================================
3 @profile
4 5.97 MB 0.00 MB def my_func():
5 13.61 MB 7.64 MB a = [1] * (10 ** 6)
6 166.20 MB 152.59 MB b = [2] * (2 * 10 ** 7)
7 13.61 MB -152.59 MB del b
8 13.61 MB 0.00 MB return a
Примеры приведены в документах, связанных выше.

10.03.2019 10:35:36
Будьте осторожны timeit
очень медленный, это займет 12 секунд на моем среднем процессоре, чтобы просто инициализировать (или, может быть, запустить функцию). вы можете проверить этот принятый ответ
def test():
lst = []
for i in range(100):
lst.append(i)
if __name__ == '__main__':
import timeit
print(timeit.timeit("test()", setup="from __main__ import test")) # 12 second
для простой вещи я буду использовать time
вместо этого, на моем ПК он возвращает результат 0.0
import time
def test():
lst = []
for i in range(100):
lst.append(i)
t1 = time.time()
test()
result = time.time() - t1
print(result) # 0.000000xxxx

timeit
запускает вашу функцию много раз, чтобы усреднить шум. Количество повторов-это опция, смотрите сравнительный анализ времени выполнения в python или более позднюю часть принятого ответа на этот вопрос.


30.05.2019 09:34:17
Если вы не хотите писать шаблонный код для timeit и легко анализировать результаты, взгляните на benchmarkit . Кроме того, он сохраняет историю предыдущих запусков, так что легко сравнить одну и ту же функцию в ходе разработки.
# pip install benchmarkit
from benchmarkit import benchmark, benchmark_run
N = 10000
seq_list = list(range(N))
seq_set = set(range(N))
SAVE_PATH = '/tmp/benchmark_time.jsonl'
@benchmark(num_iters=100, save_params=True)
def search_in_list(num_items=N):
return num_items - 1 in seq_list
@benchmark(num_iters=100, save_params=True)
def search_in_set(num_items=N):
return num_items - 1 in seq_set
benchmark_results = benchmark_run(
[search_in_list, search_in_set],
SAVE_PATH,
comment='initial benchmark search',
)
Выводит на терминал и возвращает список справочников с данными для последнего запуска. Точки входа командной строки также доступны.
При изменении N=1000000
и повторном запуске

16.01.2020 05:57:59
snakeviz
interactive viewer для cProfile
https://github.com/jiffyclub/snakeviz/
cProfile был упомянут на https://stackoverflow.com/a/1593034/895245 и змеевиз был упомянут в комментарии, но я хотел бы подчеркнуть это далее.
Очень трудно отладить производительность программы, просто глядя На cprofile
cprofile / pstats
, потому что они могут только суммировать время на функцию из коробки.
Однако, что нам действительно нужно в целом, так это увидеть вложенное представление, содержащее трассировки стека каждого вызова, чтобы действительно легко найти основные узкие места.
И это именно то, что snakeviz предоставляет через свой стандартный вид "сосульки".
Сначала вы должны сбросить данные cProfile в двоичный файл, а затем вы можете snakeviz на этом
pip install -u snakeviz
python -m cProfile -o results.prof myscript.py
snakeviz results.prof
Это выводит URL-адрес stdout, который вы можете открыть в своем браузере, который содержит желаемый вывод, который выглядит следующим образом:
и тогда вы сможете:
- наведите курсор на каждое поле, чтобы увидеть полный путь к файлу, содержащему функцию
- нажмите на поле, чтобы это поле появилось в верхней части, чтобы увеличить масштаб.
Более профильный вопрос: Как вы можете профилировать скрипт Python?