Делаем свой таймер на Python
Код — проще, возможностей — больше.
У нас когда-то был мини-проект: сделать свой таймер-напоминалку, который спрашивает, про что вам напомнить, а потом выдаёт сообщение через нужное время. В прошлый раз мы его сделали на JavaScript, теперь напишем на Python. Потому что Python — это модно, красиво и приятно.
Отличия и особенности
JavaScript прекрасен тем, что его можно запустить в консоли любого современного браузера. Это для него родная среда, и JS легко работает со страницами, объектами на ней, вкладками браузера и всем, что с ним связано.
Python — более универсальный язык, который работает не только с браузерами, поэтому для него нужен отдельный интерпретатор. Интерпретатор — это программа, которая берёт исходный код и выполняет команду за командой. Вы можете написать отличный код, но чтобы его исполнить, вам всегда нужен будет интерпретатор.
Есть два способа запустить Python-код:
1. Поставить Python себе на компьютер — этот способ хорош, если вы решили основательно изучить язык или просто любите, когда всё быстро и под контролем. Скачать Python можно с официального сайта — есть версии для всех основных операционных систем.
Из минусов — нужно разбираться в параметрах установки и настройки и уметь работать с командной строкой.
Плюсы — полный контроль и быстродействие.
2. Использовать онлайн-сервисы, например, этот: onlinegdb.com/online_python_compiler. Работает точно так же — пишете код, нажимаете кнопку Run и смотрите на результат.
Минусы: так как это онлайн-сервис, им пользуется одновременно много человек, поэтому быстродействия от него ждать не стоит. С подключением внешних модулей тоже могут возникнуть проблемы, но с этим можно разобраться, если потратить немного времени.
Плюс: не нужно ничего настраивать и устанавливать, всё работает сразу из браузера. Есть подсветка синтаксиса, сообщения об ошибках и возможность сохранения кода.
Сейчас мы напишем таймер с оглядкой на онлайновый сервис. А отдельно ещё расскажем об установке.
Исходный код на JavaScript
Что мы здесь сделали:
Особенность Python в том, что в нём нет встроенных средств работы с браузером и его вкладками, поэтому помигать заголовком пока не получится. С другой стороны, Python не зависит от браузера, поэтому будем использовать штатные средства ввода и вывода сообщений.
Простая реализация на Python
Самое простое, что можно сделать — поставить программу на паузу на нужное время, а потом вывести сообщение. Для этого подключаем стандартный модуль time — он отвечает за работу со временем.
Модуль в Python — это уже готовый python-файл, где собраны запчасти, которые помогают решать какую-то узкую задачу: функции и классы. Например, замерять время, работать с математическими функциями или календарём.
Чтобы сделать паузу, используют команду time.sleep(). Time — это название модуля, который мы подключили, а sleep — функция, которая находится внутри модуля. Её задача — подождать нужное количество секунд, а потом продолжить выполнение программы.
Что дальше: многозадачность и оптимизация
Наша программа уже работает как нужно, но её можно улучшить. Дело в том, что ставить весь код на паузу — не самое удачное решение с точки зрения производительности. Представьте, что вам нужно поставить себе несколько напоминаний на разное время. С таким подходом нам придётся выяснять, какое сработает раньше, потом корректировать время паузы для следующего напоминания и так далее.
Можно сделать так: выносить напоминания в отдельные потоки. Это как подпрограмма, которая работает параллельно с нашей программой и не сильно зависит от неё. Это позволит не ждать первого события, а запускать их одновременно. Но про всё это — в следующем материале.
Понимание класса таймера Python с примерами
Если мы хотим задержать выполнение функции на определенное время, мы можем использовать класс python timer. start() и cancel () – это два его метода.
Понимание класса таймера Python с примерами
Python имеет тысячи модулей и библиотек для удовлетворения потребностей программиста. Однако, чтобы сделать их полезными, вы должны сначала понять их, а затем применить. Без предварительного знания определенных модулей неясно, что вы хотите сделать и что на самом деле делает модуль. Время-один из важных факторов в задачах кодирования. Все коды предназначены для того, чтобы уменьшить работу человека, используя свои мощные алгоритмы. Тайм-менеджмент оказывает большое влияние на анализ производительности вашего кода. Вот почему сегодня мы подробно узнаем о том, как работает таймер в Python.
Python Timer-это класс/библиотека для управления временной сложностью вашего кода. Используя несколько временных модулей, вы можете создать систему в своем коде, чтобы проверить время, затраченное соответствующим фрагментом кода. Существуют различные типы реализаций таймера в python в соответствии с потребностями пользователя, а именно функция таймера python (для проверки времени выполнения скрипта), таймер потоковой передачи python (для проверки времени, затраченного потоком на завершение), таймер обратного отсчета python (создание таймера обратного отсчета) и базовый модуль времени python (для помощи в других действиях).
Все эти реализации таймера функционируют по-разному и фокусируются на предоставлении различного использования конечному пользователю. В этом посте мы подробно рассмотрим каждую реализацию таймера. Вы можете использовать Оглавление, чтобы перейти к соответствующей реализации таймера python.
Основные Функции Таймера Python
Самый важный модуль в python относительно времени-это href=”https://docs.python.org/3/library/time.html”>время. Этот модуль содержит все основные функции для проверки времени и его анализа. Этот анализ поможет вам понять производительность вашего кода и его эффективность. Мы рассмотрим каждую из важных функций этого модуля вместе с примерами. href=”https://docs.python.org/3/library/time.html”>время. Этот модуль содержит все основные функции для проверки времени и его анализа. Этот анализ поможет вам понять производительность вашего кода и его эффективность. Мы рассмотрим каждую из важных функций этого модуля вместе с примерами.
Ниже приведены основные функции таймера Python, использующие модуль time –
Функция time.time
time.time() возвращает время в секундах (float) после эпохи. Как правило, эпоха устанавливается на январь 1, 1970, 00:00:00 (UTC), и возвращается количество секунд после этой эпохи. Эта функция зависит от времени компьютера для вычисления количества секунд. Если вы измените компьютерное время между выполнением python, вы можете получить странные числа, используя эту функцию.
Во-первых, мы начинаем с импорта модуля времени. Этот модуль содержит все основные функции времени, которые мы будем использовать в этом разделе. В начале кода мы объявим переменную start как time.time(). Это сохранит текущее время процессора в float number из эпохи. Мы будем использовать эту начальную переменную в качестве ориентира для измерения времени. Следующая часть содержит все коды, которые вы хотите использовать (В этом примере мы использовали циклы for).Аналогично, запишите время окончания работы процессора (время по умолчанию) и проверьте общее время выполнения с помощью end – start.
Это выведет время, затраченное кодом в секундах. С помощью этой техники вы можете проверить время, затраченное вашим кодом. Единственная проблема с этим методом заключается в том, что процессорное время может быть изменено во время выполнения кода. Это приведет к проблемному поведению в python timer.
Функциональное время.Thread_time
time.thread_time() возвращает сумму системного и процессорного времени (float) в текущем запущенном потоке. Более того, он не включает в себя время, которое вы проводите в функции time.sleep(). Поскольку функция зависит от потока, вы можете использовать эту функцию для записи временных различий до тех пор, пока ссылки на время принадлежат одному и тому же потоку.
Функциональное время.Process_time
time.process_time() возвращает ссылку на время в дробных секундах (float) суммы системного времени и процессорного времени текущего прогресса. Как и thread_time, эта функция не измеряет время, проведенное в функции time.sleep(). Более того, эта функция создает ссылку на основе процесса. As в результате этого будет иметь смысл только разница во времени между двумя последовательными ссылками.
Мы начинаем с импорта функции process_time и записываем время начала и окончания между кодом. Единственное различие между устаревшими time.time() и time.process_time() заключается в том, что processing time записывает временные ссылки текущего процесса, тогда как time() записывает абсолютное время системы.
Время работы.Perf_counter
Perf Counter расшифровывается как Performance Counter. Эта функция возвращает значение с высоким разрешением времени, которое является действительным в течение короткого периода времени. Эта функция используется для получения точного отсчета времени между двумя ссылками. Поскольку другие функции таймера python не включают время сна, perf_counter также не включает его. Давайте перейдем к примеру –
Счетчик perf можно использовать так же, как таймер процесса или таймер потока. Разница лишь в том, что счетчик perf вернет высокое точное значение прошедшего времени. Но убедитесь, что вы используете этот между небольшими процессами, так как он использует высокую точность. Мы использовали простой цикл, чтобы проверить время, затраченное им.
Функция времени.монотонная
Сначала мы импортируем монотонную функцию из модуля времени. Затем создайте две ссылки с именами start и end в верхней и нижней части кода. Это позволит измерить время между двумя ссылками и избежать всех внешних изменений системного времени.
Пользовательские Классы таймера Python
Вы можете создать свой собственный класс таймера, чтобы делать все в соответствии с вашими потребностями. Одним из главных преимуществ создания пользовательского класса является то, что вы можете управлять всем временем в одной строке. Вам не нужно каждый раз импортировать класс time и записывать ссылки. Кроме того, вы можете сбросить свои данные и записать все прошлые исполнения времени, чтобы выбрать лучший алгоритм для вас.
В этом разделе будет создан пользовательский класс для управления временем и регистрации всех временных различий в ваших кодах. Давайте нырнем прямо в него –
Начнем с импорта модуля времени. Затем инициализируйте класс таймера python и начните определять атрибуты и методы. До сих пор мы включали только базовый атрибут, чтобы сохранить начальную ссылку класса. Чтобы сделать его более сложным, вы можете создать несколько атрибутов. На данный момент существует три метода, перечисленных ниже –
Примеры использования вышеуказанного класса приведены ниже. Как вы можете видеть, вы можете сохранить свой код чистым, создав пользовательский класс таймера и повысив гибкость.
Таймер Python с использованием потоковой передачи
Когда мы хотим выполнить какую-то операцию или хотим, чтобы наша функция выполнялась через определенное время, мы используем класс Python Timer. Класс timer является подклассом класса threading. Технически можно сказать, что мы создаем объекты таймера, когда хотим, чтобы действия (функции) были ограничены временем.
Синтаксис класса Timer в Python
Если вы не поняли, что делает класс Timer, вы можете думать об этом следующим образом – Класс Timer вызывает функцию через заданное количество секунд.
Чтобы запустить таймер, нам нужно вызвать start()(как и обычные потоки), а чтобы остановить таймер, пока он все еще находится в фоновом режиме, мы можем вызвать cancel().
Чтобы использовать класс Timer, нам нужно импортировать класс threading
Параметры-
Интервал– Время (в секундах), которое вы хотите подождать перед вызовом следующей функции. Он может быть либо в float, либо в integer. Например, в течение 3 секунд.
Функция – Функция, которую вы хотите вызвать через указанный промежуток времени.
Тип возврата-
Он просто вызывает функцию, указанную в параметрах.
Методы в классе Timer
Создание объекта таймера
Чтобы понять, как работает объект Timer, давайте создадим небольшую программу, которая поможет нам понять основы класса.
Вы лучше поймете функционирование вышеприведенной программы, когда попытаетесь запустить ее самостоятельно href=”https://en.wikipedia.org/wiki/System”>система. href=”https://en.wikipedia.org/wiki/System”>система.
б. Использование метода отмены
Давайте посмотрим, как использовать функцию cancel() класса Timer.
c. Как использовать параметр ‘args’ класса python timer
Когда нам нужно дать аргументы функции, которую нужно вызвать, мы используем параметр args. Мы должны дать аргумент args в массиве.
Теперь, когда мы много говорили о времени, в качестве бонуса давайте сделаем программу, которая будет действовать как таймер обратного отсчета.
Таймер обратного отсчета в python
Использование модуля времени
Использование класса python Timer
Таймеры Python как контекстные менеджеры
Контекстные менеджеры-это лучший способ избежать ошибок памяти и последующих сбоев. Все должны были знать о “with” заявлении в Python. Это утверждение гарантирует, что нам не нужно заботиться о том, чтобы многие объекты закрывались независимо. Каждый мог бы использовать его с комбинацией функций with и open(). Итак, переходя к главному вопросу, можем ли мы создать контекстные менеджеры для таймеров Python?
Да. Благодаря множеству функций перегрузки мы можем легко создать наш собственный таймер python в качестве контекстного менеджера всего за несколько строк. Давайте начнем с примера, где вы должны измерить время выполнения программы. Без переопределения всех переменных один контекстный менеджер может использоваться многократно для многократного измерения времени. Следующая программа демонстрирует это.
Мы начинаем с создания класса с именем “Timer_Python pool.” Затем мы настраиваем операторы, чтобы сделать их полезными в качестве контекстного менеджера. __enter__ функция выполняется в начале контекста, а __exit__ выполняется в конце контекста. Создание точки отсчета между этими двумя функциями может дать вам точное время, необходимое контексту для выполнения.
Python Timer Decorators
Декораторы-это дополнительная поддержка для любого вида функций. Также называемый метапрограммированием, вы можете изменить/добавить к нему функциональность. Python Timer Decorators-это самый простой способ реализации функций таймера в python. После объявления вы можете использовать декораторы в одной строке, даже не зная их. Кроме того, вы можете применить их к каждой функции в вашем коде, чтобы проверить, какой код занимает больше всего времени для выполнения.
Чтобы создать цепной декоратор, вам нужно объявить несколько вложенных функций. Назовите другую функцию своим основным именем декоратора и внутренним для любого случайного имени. Внутренняя функция извлекает ссылку на функцию, используемую ниже декоратора.
Как обычно, мы начинаем с импорта самого важного модуля из python “time.” Затем мы создаем декоратор с именем “check_time.” Внутри него мы добавляем вложенную внутреннюю функцию, где мы можем создавать ссылки на время. Эти две ссылки расположены так, что обе они находятся между выполнением функции.
Далее мы создаем тестовую функцию с именем “задача”, чтобы проверить, работает ли наша задача. Затем добавьте сверху декоратора. Как декоратор будет творить свою магию и печатать время, затраченное функцией.
Перезарядка таймера Python
Python Timer Cooldown-это способ измерения таймера в обратном направлении. Создавая пользовательский класс таймера, мы можем регистрировать время в каждой точке вашего кода. Вы можете экспортировать этот класс как модуль и установить его как зависимость в своем коде. Затем, используя одну строку, вы можете импортировать ее –
Другие Модули Таймера Python
Python содержит тысячи модулей и миллионы фрагментов кода. Мы всегда можем использовать модули с открытым исходным кодом для использования таймеров python. Github-это самое большое место для поиска таких модулей. Давайте сразу перейдем к этим модулям –
Должен Читать:
Вывод
В основном все используют таймеры для трех целей. Первый-это запись времени выполнения вашего кода. А во-вторых, добавить напоминание о чем-то с помощью таймера. К счастью, оба они могут быть созданы в Python. Используя различные модули и библиотеки, вы можете гарантировать, что записываете время с предельной точностью.
Попробуйте запустить программы на вашей стороне и дайте нам знать, если у вас есть какие-либо вопросы.
Модуль time в Python 3 обеспечивает доступ к нескольким различным типам, каждые из которых применяются для разных целей. Функция monotonic() может использоваться для измерения прошедшего времени в длительном процессе. Она никогда не уменьшает значение времени, даже если изменяется системное время.
Обратите внимание
Сравнение часов
Детали реализации таймера возможность которой предоставляет модуль time Python зависят от платформы. Используйте get_clock_info() для получения основной информации о текущей реализации, включая доступную точность часов:
Этот вывод для Mac OS X показывает, что Python time таймеры monotonic и perf_counter реализованы с использованием одного и того же базового системного вызова:
Основной таймер в Python
Эпоха — это начало измерения времени, которым для систем Unix является 0:00 1 января 1970 года. Хотя значение всегда является числом с плавающей запятой, фактическая точность зависит от платформы:
Десятичная дробь полезна при хранении или сравнении дат, но не для создания читаемых человеком представлений. Для регистрации или вывода времени более полезной может оказаться функция ctime() :
Второй вызов print() в этом примере иллюстрирует, как использовать ctime() для форматирования значения времени, которое отличается от текущего:
Таймер относительного времени
Python time() использует системные часы, которые часы могут быть изменены пользовательскими или системными службами для синхронизации часов на нескольких компьютерах. Поэтому повторяющиеся вызовы time() могут давать значения, которые отличаются в большую или в меньшую сторону. Это может привести к неожиданному поведению при попытке измерения промежутка времени.
Начальная точка для относительных таймеров не определена, поэтому возвращаемые значения могут использоваться только для расчетов с другими значениями времени. В этом примере продолжительность спящего режима измеряется с помощью monotonic() :
Таймер процессора
В этом примере отформатированная ctime() выводится вместе со значениями с плавающей запятой из time() и clock() через цикл для каждой итерации.
Примечание
Если хотите запустить этот код в своей системе, то может потребоваться добавить во внутренний цикл другие циклы или придется работать с большим количеством данных, чтобы увидеть разницу во времени с помощью Python time :
Как правило, часы процессора ничего не засекают, если программа ничего не делает:
В этом примере time sleep python цикл выполняет мало действий, переходя в спящий режим после каждой итерации. Значение time() увеличивается даже тогда, когда приложение находится в спящем режиме, но значение clock() отсутствует:
Вызов sleep() передает управление из текущего потока и указывает ожидать, пока система активирует его. Если программа имеет только один поток, это эффективно блокирует приложение, и оно не работает.
Счетчик производительности
Для измерения производительности важно иметь таймеры monotonic с высокой точностью. Определение наилучшего источника данных синхронизации требует наличия информации о платформе, которую Python предоставляет в perf_counter() :
Компоненты времени
Работа с часовыми поясами
Выбор функции для определения текущего времени зависит от того, установлен ли часовой пояс программой или системой. Изменение часового пояса не изменяет фактическое время — только способ его представления.
Обработка и форматирование времени
Функции strptime() и strftime() преобразуют struct_time в строковые представления значений времени и наоборот. Существует длинный список инструкций по форматированию для поддержки ввода и вывода в разных форматах. Полный список указан в документации библиотеки для модуля time.
В приведенном ниже примере использования модуля time Python текущее время преобразуется из строки в экземпляр struct_time и обратно в строку:
В примере с time strftime Python строка вывода не такая же, как и входная, так как день месяца имеет префикс с нулем:
Дайте знать, что вы думаете по данной теме материала в комментариях. Мы очень благодарим вас за ваши комментарии, подписки, отклики, лайки, дизлайки!
Функции тайминга Python: три способа контролировать ваш код
Хотя многие разработчики признают Python эффективным языком программирования, программы на чистом Python могут работать медленнее, чем их аналоги на скомпилированных языках, таких как C, Rust и Java. В этом руководстве вы узнаете, как использовать таймеры Python для отслеживания скорости выполнения ваших программ.
В этом уроке вы узнаете, как использовать:
Вы также получите базовые знания о том, как работают классы, контекстные менеджеры и декораторы. Поскольку будут приведены примеры каждой концепции, вы сможете по желанию использовать одну или несколько из них в своем коде, как для замера времени выполнения кода, так и для других применений. Каждый метод содержит свои преимущества, и вы узнаете, какие из них использовать в зависимости от ситуации. Кроме того, у вас будет рабочий таймер Python, который вы можете использовать для мониторинга ваших программ!
Таймеры Python
Во-первых, оснакомьтесь с некоторыми примерами кода, которые вы будете использовать на протяжении всего урока. Позже вы добавите в этот код таймер Python, для мониторинга его производительность. Вы также увидите некоторые из самых простых способов измерения времени выполнения этого примера.
Функции таймера Python
Если вы посмотрите на встроенный модуль time в Python, то заметите несколько функций, которые могут измерять время:
Возвращает значение (в долях секунд) счетчика производительности, то есть часов с самым высоким доступным разрешением для измерения короткого промежутка времени.
Во-первых, вы будете использовать perf_counter() для создания таймера Python. Позже вы сравните это с другими функциями таймера Python и узнаете, почему perf_counter() обычно является лучшим выбором.
Пример: Последовательность Фибоначчи
Чтобы лучше сравнить различные способы добавления таймера Python к своему коду, вы будете применять разные функции таймера Python к одному и тому же примеру кода в этом руководстве. Если у вас уже есть код, который вы хотели бы измерить, смело следуйте этим примерам.
Вычисление n-го числа ряда Фибоначчи с помощью цикла while:
Ваш первый таймер Python
Теперь вы можете добавить таймер Python к коду примера:
Обратите внимание, что perf_counter() вызывается как до, так и после вычисления значения функции. Затем печатается время, необходимое для вычисления, вычисляя разницу между двумя вызовами.
f-строки доступны только в Python 3.6 и более поздних версиях. Для получения дополнительной информации ознакомьтесь с официальной документацией Python 3.
Теперь, когда вы запустите пример, вы увидите потраченное время на вычисления:
Вы рассмотрели основы тайминга своего кода Python. В оставшейся части руководства вы узнаете, как можно обернуть Python-таймер в класс, менеджер контекста и декоратор, чтобы сделать его более консистентным и удобным в использовании.
Python класс Timer
В этом руководстве вы создадите и обновите класс Timer, который вы можете использовать для определения таймингов кода несколькими различными способами. Окончательный код также доступен в PyPI под названием codetiming. Вы можете установить в вашу систему следующим образом:
Понимание классов в Python
Создание класса таймера Python
Здесь происходит несколько разных вещей, поэтому давайте пройдемся по коду шаг за шагом.
Использование класса Timer :
Сравните это с предыдущим примером, где вы использовали perf_counter() напрямую. Структура кода довольно похожа, но теперь код стал более понятным, и это является одним из преимуществ использования классов. Тщательно выбирая имена классов, методов и атрибутов, вы можете сделать свой код очень информативным!
Использование класса Timer Python
Обратите внимание, что код очень похож на то, что вы видели ранее. В дополнение к тому, чтобы сделать код более читабельным, Timer заботится о печати прошедшего времени на консоль, что делает логгирование затраченного времени более последовательным. Когда вы запустите код, вы увидите примерно такой же вывод:
Печать прошедшего времени из Timer может быть последовательной, но, похоже, этот подход не очень гибкий. В следующем разделе вы увидите, как настроить свой класс.
Добавление большего удобства и гибкости
До сих пор вы видели, что классы подходят для случаев, когда вы хотите инкапсулировать состояние и обеспечивать согласованное поведение в вашем коде. В этом разделе вы добавим больше удобств и гибкости вашему таймеру Python:
После обновления timer.py вы можете изменить текст следующим образом:
Вот два примера, которые показывают новую функциональность в действии:
Когда вы запускаете эти примеры в интерактивной оболочке, Python автоматически печатает возвращаемое значение.
Одна тонкая проблема с этим кодом заключается в том, что вы измеряете не только время, необходимое для вычисления элемента последовательности, но и время, которое Python тратит на печать результатов на экран. Это может быть не так важно, поскольку время, потраченное на печать, должно быть незначительным по сравнению со временем, потраченным на вычисления. Тем не менее, было бы хорошо иметь возможность точно определить время.
Переменные класса могут быть доступны либо непосредственно в классе, либо через экземпляр класса:
В обоих случаях код возвращает один и тот же пустой словарь классов.
Затем добавим дополнительные имена к вашему таймеру Python. Вы можете использовать имя для двух разных целей:
Теперь вернёмся к series_numbers.py и убедиться, что измеряется только время, потраченное на вычисления:
Повторный запуск сценария даст такой же результат, как и раньше, хотя сейчас измеряется только фактическое время вычислений:
Последняя строка является способом, которым Python представляет объекты по умолчанию. Хотя вы можете почерпнуть из него некоторую информацию, она обычно не очень полезна. Вместо этого было бы неплохо увидеть такие вещи, как имя Timer или как он будет сообщать о времени.
В Python 3.7 классы данных были добавлены в стандартную библиотеку. Они обеспечивают несколько удобств для ваших классов, включая более информативную строку представления.
Вот несколько заметок о классе данных Timer :
Новый класс данных Timer работает так же, как ваш предыдущий обычный класс, за исключением того, что теперь он имеет хорошее представление:
Прежде чем закончить этот раздел, давайте взглянем на полный исходный код Timer в его нынешнем виде. Вы заметите добавление подсказок типа к коду для дополнительной документации:
Использование класса для создания таймера, Python предлагает несколько преимуществ:
Класс очень гибкий, и вы можете использовать его практически в любой ситуации, когда вы хотите отслеживать время, необходимое для выполнения кода. Тем не менее, в следующих разделах вы узнаете об использовании менеджеров контекста и декораторов, которые будут более удобными для замеров блоков кода и функций.
Менеджер контекста Python Timer
Python класс Timer прошел долгий путь! По сравнению с первым созданным таймером Python код стал достаточно мощным. Тем не менее, для использования таймера все еще есть немного стандартного кода:
Понимание контекстных менеджеров в Python
Менеджеры контекста были частью Python в течение долгого времени. Они были представлены PEP 343 в 2005 году и впервые реализованы в Python 2.5. Вы можете распознать контекстные менеджеры в коде с помощью ключевого слова with :
Наиболее распространенное использование контекстных менеджеров, вероятно, обработка различных ресурсов, такие как файлы, блокировки и соединения с базой данных. Затем менеджер контекста используется для освобождения и очистки ресурса после его использования. В следующем примере раскрывается фундаментальная структура timer.py путем печати только строк, содержащих двоеточие. Что еще более важно, он показывает общую идиому для открытия файла в Python:
Что это значит, что fp является контекстным менеджером? Технически это означает, что fp реализует протокол менеджера контекста. В основе языка Python лежит много разных протоколов. Вы можете думать о протоколе как о контракте, в котором указано, какие конкретные методы должен реализовывать ваш код.
Протокол менеджера контекста состоит из двух методов:
Вы можете увидеть, что «See you later, Rascal» печатается, даже если в коде есть ошибка.
Теперь вы знаете, что такое контекстные менеджеры и как вы можете создать свой собственный. Если вы хотите погрузиться глубже, то посмотрите contextlib в стандартной библиотеке. Он включает в себя удобные способы определения новых контекстных менеджеров, а также готовые контекстные менеджеры, которые можно использовать для закрытия объектов, устранения ошибок или даже бездействия!
Создание менеджера контекста Python Timer
Вы также должны отметить еще две тонкие детали:
Использование менеджера контекста Python Timer
Давайте посмотрим, как использовать менеджер контекста Timer для определения времени вычисления числа Фибоначчи. Вспомните, как вы использовали Timer ранее:
Запуск скрипта должен дать знакомый результат:
Есть несколько преимуществ для добавления возможностей менеджера контекста к вашему классу таймера Python:
Python Timer декоратор
Ваш класс Timer теперь очень универсален. Однако есть один вариант использования, где он может быть еще более упорядоченным. Скажем, вы хотите отслеживать время, проведенное внутри одной данной функции в вашей кодовой базе. Используя контекстный менеджер, у вас есть два основных варианта:
1. Используйте Timer каждый раз, когда вы вызываете функцию:
Если вы вызовете do_something() во многих местах, это станет громоздко и сложно в обслуживании.
2. Обернём код функцией содержащей внутри контекстный менеджер:
Понимание декораторов в Python
В качестве первого примера создадим декоратор, который ничего не делает:
Вместо этого create_multiplier() используется для создания новых функций умножения, каждая из которых основана на различном factor :
Символ @ используется для применения декораторов. В этом случае @triple означает, что triple() применяется к функции, определенной сразу после нее.
Иногда декорированные функции должны иметь правильные метаданные. @functools.wraps исправляют именно эту проблему:
С новым определением @triple метаданные сохраняются:
Обратите внимание, что knock() теперь сохраняет свое собственное имя, даже после того, как был декорирован. Это хорошая форма, чтобы использовать @functools.wraps всякий раз, когда вы определяете декоратор. Схема, которую вы можете использовать для большинства ваших декораторов, выглядит следующим образом:
Создание декоратора Timer Python
В этом разделе вы узнаете, как расширить свой таймер Python, чтобы вы также могли использовать его в качестве декоратора. Однако в качестве первого упражнения давайте создадим Python декоратор Timer с нуля.
Основываясь на приведенной выше схеме, вам нужно только решить, что делать до и после вызова декорированной функции. Это похоже на соображения о том, что делать при входе и выходе из контекстного менеджера. Вы хотите запустить таймер Python перед вызовом декорированной функции и остановить таймер Python после завершения вызова. Декоратор @timer может быть определен следующим образом:
Обратите внимание, насколько wrapper_timer() напоминает ранний шаблон, установленный вами для замеров кода Python. Вы можете применить @timer следующим образом:
Напомним, что вы также можете применить декоратор к ранее определенной функции:
Поскольку @ применяется при определении функций, в этих случаях необходимо использовать более простую форму. Одно из преимуществ использования декоратора заключается в том, что вам нужно применить его только один раз, и он будет каждый раз определять время выполнения функции:
@timer делает свою работу. Тем не менее, в некотором смысле вы вернулись к исходной точке, поскольку @timer не обладает никакой гибкостью или удобством Timer. Можете ли вы также заставить свой класс Timer действовать как декоратор?
Здесь square-это экземпляр, который может быть вызван и может содержать квадрат числа, точно так же, как функция square() в первом примере.
Это дает вам возможность добавить возможности декоратора к существующему классу таймера:
Теперь вы можете использовать Timer в качестве декоратора:
Прежде чем завершить этот раздел, знайте, что есть более простой способ превратить ваш таймер Python в декоратор. Вы уже видели некоторые сходства между контекстными менеджерами и декораторами. Они оба обычно используются для выполнения чего-то до и после выполнения некоторого заданного кода.
Использование декоратора таймера Python
Если вы сравните эту реализацию с оригинальной реализацией без какого-либо времени, то заметите, что единственными различиями являются импорт Timer в строке 3 и применение @Timer() в строке 6. Существенным преимуществом использования декораторов является то, что они обычно просты в применении, как вы видите.
Тем не менее, декоратор по-прежнему относится ко всей функции. Это означает, что ваш код учитывает время, необходимое для печати результата. Давайте запустим сценарий в последний раз:
Расположение выходных данных прошедшего времени является предательским признаком того, что ваш код также учитывает время, необходимое для печати времени. Как вы видите здесь, ваш код печатает прошедшее время после вычислений.
При использовании таймера в качестве декоратора вы увидите те же преимущества, что и при использовании контекстных менеджеров:
Однако декораторы не так гибки, как контекстные менеджеры. Вы можете применять их только для выполнения функций. Можно добавить декораторы к уже определенным функциям, но это немного неуклюже и менее распространено.
Код Timer Python
Вы можете использовать код самостоятельно, сохранив его в файле с именем timer.py и импортировать его в вашу программу. Запустим новый таймер в качестве менеджера контекста:
Этот вид таймера Python в основном полезен для мониторинга времени, которое ваш код тратит на отдельные ключевые блоки кода или функции. В следующем разделе вы получите краткий обзор альтернатив, которые можно использовать, если вы хотите оптимизировать свой код.
Другие функции таймеры в Python
Существует множество вариантов замеров выполнения вашего кода Python. В этом уроке вы узнаете, как создать гибкий и удобный класс, который можно использовать несколькими различными способами. Быстрый поиск по PyPI показывает, что уже существует множество проектов, предлагающих решения тайминга Python.
В этом разделе вы сначала узнаете больше о различных функциях, доступных в стандартной библиотеке для измерения времени, и о том, почему perf_counter() предпочтительнее. Затем вы увидите альтернативы оптимизации вашего кода, для которых таймер не очень хорошо подходит.
Использование альтернативных функций таймеров в Python
Вы использовали perf_counter() на протяжении всего этого урока для выполнения фактических измерений времени, но библиотека time Python поставляется с несколькими другими функциями, которые также измеряют время. Вот некоторые альтернативы:
Одна из причин, почему существует несколько функций, заключается в том, что Python представляет время как float. Числа с плавающей запятой по своей природе неточны. Возможно, вы уже видели подобные результаты раньше:
Float Python следует стандарту IEEE 754 для арифметики с плавающей запятой, который пытается представить все числа с плавающей запятой в 64 битах. Поскольку существует бесконечно много чисел с плавающей запятой, вы не можете выразить их в виде конечного числа битов.
IEEE 754 предписывает систему, в которой плотность чисел, которые вы можете представить, изменяется. Чем ближе вы к 1, тем больше чисел вы можете представить. Для больших чисел есть больше пространства между числами, которые вы можете выразить. Это имеет некоторые последствия, когда вы используете float для представления времени.
Здесь вы видите, что добавление наносекундного числа на самом деле влияет на результат.
Поскольку perf_counter() уже обеспечивает наносекундное разрешение, у использования perf_counter() меньше преимуществ.
Примечание: perf_counter_ns() доступен только в Python 3.7 и более поздних версиях. В этом уроке вы использовали perf_counter() в своем классе Timer. Таким образом, таймер можно использовать и в более старых версиях Python. Для получения дополнительной информации о функциях _ns в time ознакомьтесь с новыми классными функциями в Python 3.7.
Результаты могут быть разными в вашей системе.
PIP 418 описывает некоторые обоснования введения этих функций. Она включает в себя следующие краткие описания:
Как вы можете видеть, обычно это лучший выбор для вас, чтобы использовать perf_counter() для вашего таймера Python.
Оценка времени работы со временем timeit
Допустим, нужно выжать из кода последний бит производительности и задаетесь вопросом о наиболее эффективном способе преобразования списка в множество. Вы хотите сравнить, использование set() и литерал множества <. >. Для этого вы можете использовать свой таймер Python:
Этот тест, по-видимому, указывает на то, что литерал множества может быть немного быстрее. Однако эти результаты довольно неопределенные, и если вы повторно запустите код, можно получить совершенно другие результаты. Это потому, что вы только один раз пробуете код. Например, вам может не повезти, и вы можете запустить сценарий как раз в тот момент, когда ваш компьютер будет занят другими задачами.
Лучше всего воспользоваться стандартной библиотекой. Она предназначен именно для измерения времени выполнения небольших фрагментов кода. Для этого импортируем и вызовем timeit.timeit() из Python как обычную функцию в интерфейсе командной строки. Вы можете рассчитать эти два варианта следующим образом:
Примечание: будьте осторожны, когда вы используете timeit на коде, который может загружать файлы или получать доступ к базам данных. Поскольку время от времени он автоматически вызывает вашу программу несколько раз, вы можете непреднамеренно в конечном итоге заспамить сервер запросами!
Наконец, интерактивная оболочка IPython и Jupyter notebook имеют дополнительную поддержку этой функции с помощью команды %timeit magic :
Опять же, измерения показывают, что использование литерала множества происходит быстрее.
Поиск узких мест в коде с помощью профилирования
timeit отлично подходит для бенчмаркинга конкретного фрагмента кода. Однако было бы очень громоздко использовать его для проверки всех частей вашей программы и определения того, какие разделы занимают больше всего времени. Вместо этого можно использовать профилировщик.
Этот вывод показывает, что общее время выполнения составило 0.002 секунды. В нем также перечислены десять функций, на которые ваш код потратил большую часть своего времени. Здесь вы отсортированы по кумулятивному времени (cumtime), что означает, что ваш код считает время, когда данная функция вызвала другую функцию.
Столбец общее время (tottime) показывает, сколько времени ваш код провел внутри функции, исключая время в подфункциях. Вы можете видеть, что ни одна из вышеперечисленных функций на самом деле не тратит на это никакого времени. Чтобы найти, где код провел большую часть своего времени, выполните другую команду sort :
Вы можете использовать статистику, чтобы получить некоторое представление о том, где ваш код тратит большую часть своего времени, и посмотреть, сможете ли вы оптимизировать любые узкие места, которые вы найдете. Вы также можете использовать этот инструмент, чтобы лучше понять структуру вашего кода. Например, вызываемые и вызывающие команды покажут вам, какие функции вызывают и вызываются данной функцией.
Для получения более мощного интерфейса для анализа данных профиля, запустите программу KCacheGrind. Он использует свой собственный формат данных, но вы можете конвертировать данные из профиля с помощью pyprof2calltree :
Примечание: Вы также можете профилировать потребление памяти вашего кода. Это выходит за рамки данного руководства. Однако вы можете взглянуть на memory-profiler, если вам нужно контролировать потребление памяти вашими программами.
Обратите внимание, что line_profiler требует времени и добавляет изрядную часть накладных расходов к вашей среде выполнения. Более стандартный рабочий процесс заключается в том, чтобы сначала использовать cProfile для определения того, какие функции нужно просмотреть, а затем запустить line_profiler для этих функций. line_profiler не является частью стандартной библиотеки, поэтому вы должны сначала следовать инструкциям по установке, чтобы настроить его.
Перед запуском профилировщика необходимо указать ему, какие функции следует профилировать. Это выполняется, добавлением декоратора @profile в свой исходный код. Например, для профилирования Timer.stop() вы добавляете следующее в timer.py :
Вывод
В этом руководстве вы увидели несколько разных подходов к добавлению таймера Python в свой код:
Теперь вы можете добавить функции Timer Python в свой собственный код! Отслеживание скорости выполнения вашей программы в журналах поможет вам отслеживать ваши сценарии.