Модуль datetime
Содержание:
- Сравните производительность блоков кода
- The time Module
- datetime.datetime
- Получение форматированной строки с датой и временем.
- Properties and Duration Methods
- Period
- Times
- Вызов sleep() с Async IO на примерах
- Python format datetime
- Измерение производительности небольших фрагментов кода.
- Python Interface¶
- Работа с часовыми поясами
- Отличия и особенности
- Вызов sleep() с декораторами
Сравните производительность блоков кода
Мы можем легко сравнить производительность нескольких блоков кода с помощью .
Мы будем использовать для этой цели таймер, используя .
Время, затрачиваемое на блок кода, будет текущим временем минус начальное время, взятое за эталон, которое вы можете передавать через переменные.
import timeit start_time = timeit.default_timer() function_1() time_1 = timeit.default_timer() - start_time start_time = timeit.default_timer() function_2() time_2 = timeit.default_timer() - start_time print('Function 1 took', time_1) print('Function 2 took', time_2)
Давайте протестируем 2 функции в массиве numpy и и посмотрим, как они сравниваются.
import timeit import numpy as np def time_range(size): for i in range(size): pass def time_arange(size): np.arange(size) if __name__ == '__main__': # For smaller arrays print('Array size: 1000') start_time = timeit.default_timer(); time_range(1000) range_time_1 = timeit.default_timer() - start_time start_time = timeit.default_timer(); time_arange(1000) arange_time_1 = timeit.default_timer() - start_time # For large arrays print('Array size: 1000000') start_time = timeit.default_timer(); time_range(1000000) range_time_2 = timeit.default_timer() - start_time start_time = timeit.default_timer(); time_arange(1000000) arange_time_2 = timeit.default_timer() - start_time print(f'size 1000: range() took {range_time_1}') print(f'size 1000: arange() took {arange_time_1}') print(f'size 1000000: range() took {range_time_2}') print(f'size 1000000: arange() took {arange_time_2}')
Выход
Array size: 1000 Array size: 1000000 size 1000: range() took 2.2970001737121493e-05 size 1000: arange() took 8.393999451072887e-06 size 1000000: range() took 0.02567379199899733 size 1000000: arange() took 0.0031752489994687494
Таким образом, мы могли легко использовать для сравнения производительности различных функций.
The time Module
There is a popular time module available in Python which provides functions for working with times and for converting between representations. Here is the list of all available methods −
Sr.No. | Function with Description |
---|---|
1 |
time.altzone
The offset of the local DST timezone, in seconds west of UTC, if one is defined. This is negative if the local DST timezone is east of UTC (as in Western Europe, including the UK). Only use this if daylight is nonzero. |
2 |
time.asctime()
Accepts a time-tuple and returns a readable 24-character string such as ‘Tue Dec 11 18:07:14 2008’. |
3 |
time.clock( )
Returns the current CPU time as a floating-point number of seconds. To measure computational costs of different approaches, the value of time.clock is more useful than that of time.time(). |
4 |
time.ctime()
Like asctime(localtime(secs)) and without arguments is like asctime( ) |
5 |
time.gmtime()
Accepts an instant expressed in seconds since the epoch and returns a time-tuple t with the UTC time. Note : t.tm_isdst is always 0 |
6 |
time.localtime()
Accepts an instant expressed in seconds since the epoch and returns a time-tuple t with the local time (t.tm_isdst is 0 or 1, depending on whether DST applies to instant secs by local rules). |
7 |
time.mktime(tupletime)
Accepts an instant expressed as a time-tuple in local time and returns a floating-point value with the instant expressed in seconds since the epoch. |
8 |
time.sleep(secs)
Suspends the calling thread for secs seconds. |
9 |
time.strftime(fmt)
Accepts an instant expressed as a time-tuple in local time and returns a string representing the instant as specified by string fmt. |
10 |
time.strptime(str,fmt=’%a %b %d %H:%M:%S %Y’)
Parses str according to format string fmt and returns the instant in time-tuple format. |
11 |
time.time( )
Returns the current time instant, a floating-point number of seconds since the epoch. |
12 |
time.tzset()
Resets the time conversion rules used by the library routines. The environment variable TZ specifies how this is done. |
Let us go through the functions briefly −
There are following two important attributes available with time module −
Sr.No. | Attribute with Description |
---|---|
1 |
time.timezone Attribute time.timezone is the offset in seconds of the local time zone (without DST) from UTC (>0 in the Americas; <=0 in most of Europe, Asia, Africa). |
2 |
time.tzname Attribute time.tzname is a pair of locale-dependent strings, which are the names of the local time zone without and with DST, respectively. |
datetime.datetime
Объект datetime.datetime содержит всю информацию объектов datetime.date плюс datetime.time. Давайте приведем несколько примеров, для лучшего понимания разницы между этим объектом, и объектом datetime.date.
Python
import datetime
a = datetime.datetime(2017, 3, 5)
print(a) # datetime.datetime(2017, 3, 5, 0, 0)
b = datetime.datetime(2017, 3, 5, 12, 30, 10)
print(b) # datetime.datetime(2017, 3, 5, 12, 30, 10)
d = datetime.datetime(2017, 3, 5, 12, 30, 10)
print(d.year) # 2017
print(d.second) # 10
print(d.hour) # 12
1 |
importdatetime a=datetime.datetime(2017,3,5) print(a)# datetime.datetime(2017, 3, 5, 0, 0) b=datetime.datetime(2017,3,5,12,30,10) print(b)# datetime.datetime(2017, 3, 5, 12, 30, 10) d=datetime.datetime(2017,3,5,12,30,10) print(d.year)# 2017 print(d.second)# 10 print(d.hour)# 12 |
Мы видим, что datetime.datetime принимает несколько дополнительных аргументов: год, месяц, день, час, минута и секунда. Это также позволяет вам указывать информацию о микросекундах и часовом поясе. При работе с базами данных, данные типы объектов будут использоваться достаточно часто. Большую часть вашей работы, вам нужно будет конвертировать форматы date или datetime Python в форматы SQL datetime или timestamp
Обратите внимание на то, что today совместно с datetime.datetime использует два разных метода:
Python
import datetime
a = datetime.datetime.today()
print(a) # datetime.datetime(2017, 4, 5, 0, 16, 54, 989663)
b = datetime.datetime.now()
print(b) # datetime.datetime(2017, 4, 5, 0, 17, 8, 24239)
1 |
importdatetime a=datetime.datetime.today() print(a)# datetime.datetime(2017, 4, 5, 0, 16, 54, 989663) b=datetime.datetime.now() print(b)# datetime.datetime(2017, 4, 5, 0, 17, 8, 24239) |
Модуль datetime содержит другой метод, под названием strftime. Этот метод позволяет разработчику создавать строку, отображающую время в более понятной для человека форме. Существует целая таблица параметров форматирования, с которой рекомендуется ознакомиться в документации Python, в . Давайте взглянем на несколько примеров, показывающих всю полезность данного метода:
Python
import datetime
a = datetime.datetime.today().strftime(«%Y%m%d»)
print(a) # ‘20170405’
today = datetime.datetime.today()
print( today.strftime(«%m/%d/%Y») ) # ’04/05/2017′
print( today.strftime(«%Y-%m-%d-%H.%M.%S») ) # 2017-04-05-00.18.00
1 |
importdatetime a=datetime.datetime.today().strftime(«%Y%m%d») print(a)# ‘20170405’ today=datetime.datetime.today() print(today.strftime(«%m/%d/%Y»))# ’04/05/2017′ print(today.strftime(«%Y-%m-%d-%H.%M.%S»))# 2017-04-05-00.18.00 |
Первый пример – это скорее хитрость. В нем показано, как конвертировать сегодняшний объект datetime в строку, следующую за форматом YYYYMMDD (ГГГГММДД). Второй пример более наглядный.
В нем мы присваиваем объект datetime переменной под названием today и применяем два разных параметра форматирования строки. Первый параметр добавляет косые черточки между элементами datetime, а также перегруппировывает datetime, теперь он делится на месяц, день и год. В последнем примере мы создаем временную отметку, которая следует типичному формату: YYYY-MM-DD.HH.MM.SS. Если вам нужно указать год как двухзначный (“YY”), вы можете заменить %Y на %y.
Получение форматированной строки с датой и временем.
Описание:
Функция модуля преобразовывает кортеж или структуру времени , представляющие время, возвращаемое или в строку, указанную форматом .
Если аргумент не указан, используется текущее время, возвращаемое функцией . Формат должен быть строкой. Если какое-либо поле в структуре находится вне допустимого диапазона, то вызывается исключение .
Значение 0 является допустимым аргументом для любой позиции в именованном кортеже структуры. Если это некорректный параметр, то значение принудительно устанавливается на правильное.
Следующие директивы могут быть встроены в строку формата. Они отображаются без указания необязательной ширины поля и точности и заменяются указанными символами в результате работы :
Директива | Смысл | Примечание |
Сокращенное название дня недели. | ||
Полное название дня недели. | ||
Сокращенное название месяца в локали. | ||
Полное название месяца в локали. | ||
Соответствующая локали дата и время. | ||
День месяца в виде десятичного числа . | ||
Час (24-часовой формат) в виде десятичного числа . | ||
Час (12-часовой формат) в виде десятичного числа . | ||
День года в виде десятичного числа . | ||
Месяц как десятичное число . | ||
Минута в виде десятичного числа . | ||
Либо AM, либо PM в 12-часовом формате. | (1) | |
Секунды как десятичное число . | (2) | |
Номер недели в году (воскресенье — первый день недели) в виде десятичного числа . Все дни в новом году, предшествующем первому воскресенью, считаются на неделе 0. | (3) | |
День недели в виде десятичного числа . | ||
Номер недели в году (понедельник — первый день недели) в виде десятичного числа . Все дни в новом году, предшествующем первому понедельнику, считаются на неделе 0. | (3) | |
Соответствующее представление даты локали. | ||
Соответствующее время локали. | ||
Год без века как десятичное число . | ||
Год с веком как десятичное число. | ||
Смещение часового пояса, указывающее положительную или отрицательную разницу во времени относительно времени UTC/GMT в формате +ЧЧММ или -ЧЧММ, где Ч представляет цифры часа, а М представляет цифры минуты . | ||
Название часового пояса (без символов, если часовой пояс не существует). | ||
Буквальный символ ‘%’. |
Примечание:
- При использовании с функцией директива влияет только на час выходного поля, если для анализа часа используется директива .
- Диапазон действителен от 0 до 61. Значение 60 действительно в метках времени, представляющих високосные секунды, а значение 61 поддерживается по историческим причинам.
- При использовании с функцией директивы и используются только в вычислениях, когда указаны день недели и год.
Примеры использования:
Формат даты, указанным в стандарте электронной почты RFC 2822.
>>> from time import gmtime, strftime >>> strftime("%a, %d %b %Y %H:%M:%S +0000", gmtime()) # 'Fri, 24 Apr 2020 16:22:54 +0000'
Формат даты для записи в базу данных.
>>> from time >>> time.strftime("%Y-%m-%d", time.localtime()) # '2020-04-24'
Человеческий формат даты, используемый в обиходе.
Properties and Duration Methods
The class brings more properties than the default , and
.
If you want to get the duration in each supported unit
you can use the appropriate methods.
Similarly, the methods return the total duration in each
supported unit as a truncated integer.
It also has a handy method, which determines the duration representation when printed.
Period
When you subtract a instance from another, or use the method, it will return a instance.
It inherits from the class with the added benefit that it is aware of the
instances that generated it, so that it can give access to more methods and properties:
Be aware that a period, just like an interval, is compatible with the class regarding
its attributes. However, its custom attributes (like ) will be aware of any DST
transitions that might have occurred and adjust accordingly. Let’s take an example:
Warning
Due to their nature (fixed duration between two datetimes), most arithmetic operations will
return a instead of a .
Times
Times is a small, minimalistic, Python library for dealing with time
conversions to and from timezones, for once and for all.
Accepting time
Never work with _local_ times. Whenever you must accept local time input (e.g.
from a user), convert it to universal time immediately:
`pycon
>>> times.to_universal(local_time, 'Europe/Amsterdam')
datetime.datetime(2012, 2, 1, 10, 31, 45, 781262)
`
The second argument can be a pytz.timezone instance, or a timezone string.
If the local_time variable already holds timezone info, you _must_ leave out
the source timezone from the call.
To enforce best practices, times will never implicitly convert times for you,
even if that would technically be possible.
Date Strings
If you want to accepting datetime representations in string form (for example,
from JSON APIs), you can convert them to universal datetimes easily:
`pycon
>>> import time, times
>>> print times.to_universal('2012-02-03 11:59:03-0500') # auto-detects source timezone
`
Times utilizes the string parsing routines available in . Note
that the source timezone is auto-detected from the string. If the string
contains a timezone offset, you are not allowed to explicitly specify one.
If the string does not contain any timezone offset, you _must_ specify the
source timezone explicitly:
`pycon
>>> print times.to_universal('2012-02-03 11:59:03', 'Europe/Amsterdam')
`
This is the inverse of times.format().
POSIX timestamps
If you prefer working with UNIX (POSIX) timestamps, you can convert them to
safe datetime representations easily:
`pycon
>>> import time, times
>>> print times.to_universal(time.time())
2012-02-03 11:59:03.588419
`
Note that to_universal auto-detects that you give it a UNIX timestamp.
To get the UNIX timestamp representation of a universal datetime, use:
`pycon
>>> print times.to_unix(universal_time)
`
Current time
When you want to record the current time, you can use this convenience method:
`pycon
>>> import times
>>> print times.now()
datetime.datetime(2012, 2, 1, 11, 51, 27, 621491)
`
Вызов sleep() с Async IO на примерах
Асинхронные возможности были добавлены в Python 3.4, и с тех пор данный аспект постоянно распространяется и улучшается. Асинхронное программирование является типом параллельного программирования, что позволяет одновременно запускать множество задач. По завершении задачи выводится уведомления для основного потока.
Модуль asyncio позволяет добавлять в Python вызов асинхронно.
Вот пример, данный в официальной документации Python:
Python
import asyncio
async def main():
print(‘Hello …’)
await asyncio.sleep(1)
print(‘… World!’)
# Python 3.7+
asyncio.run(main())
1 6 |
importasyncio async defmain() print(‘Hello …’) print(‘… World!’) asyncio.run(main()) |
В данном примере запускается , что погружается в сон на секунду между двумя вызовами .
Вот более подробный пример из раздела о Сопрограммах и задачах документации :
Python
import asyncio
import time
async def output(sleep, text):
await asyncio.sleep(sleep)
print(text)
async def main():
print(f»Started: {time.strftime(‘%X’)}»)
await output(1, ‘First’)
await output(2, ‘Second’)
await output(3, ‘Third’)
print(f»Ended: {time.strftime(‘%X’)}»)
# Python 3.7+
asyncio.run(main())
1 6 13 |
importasyncio importtime async defoutput(sleep,text) print(text) async defmain() print(f»Started: {time.strftime(‘%X’)}») await output(1,’First’) await output(2,’Second’) print(f»Ended: {time.strftime(‘%X’)}») asyncio.run(main()) |
В данном коде создается рабочий поток , что принимает количество секунд для и выводит . После этого используется ключевое слово Python для ожидания запуска кода . Здесь требуется , так как был отмечен как функция , и теперь не может вызываться как обычная функция.
При запуске кода программа выполнит 3 раза. Код будет ждать 1, 2 и 3 секунды, общее время ожидания равно 6 секундам. Можно также переписать код таким образом, чтобы задачи выполнялись параллельно:
Python
import asyncio
import time
async def output(text, sleep):
while sleep > 0:
await asyncio.sleep(1)
print(f'{text} counter: {sleep} seconds’)
sleep -= 1
async def main():
task_1 = asyncio.create_task(output(‘First’, 1))
task_2 = asyncio.create_task(output(‘Second’, 2))
task_3 = asyncio.create_task(output(‘Third’, 3))
print(f»Started: {time.strftime(‘%X’)}»)
await task_1
await task_2
await task_3
print(f»Ended: {time.strftime(‘%X’)}»)
if __name__ == ‘__main__’:
asyncio.run(main())
1 |
importasyncio importtime async defoutput(text,sleep) whilesleep> await asyncio.sleep(1) print(f'{text} counter: {sleep} seconds’) sleep-=1 async defmain() task_1=asyncio.create_task(output(‘First’,1)) task_2=asyncio.create_task(output(‘Second’,2)) task_3=asyncio.create_task(output(‘Third’,3)) print(f»Started: {time.strftime(‘%X’)}») await task_1 await task_2 await task_3 print(f»Ended: {time.strftime(‘%X’)}») if__name__==’__main__’ asyncio.run(main()) |
Теперь вы используете концепт задач, что можно создать через . При использовании задач в Python будет запускать задачи асинхронно. Таким образом, выполнение программы завершится через 3 секунды вместо 6.
Python format datetime
The way date and time is represented may be different in different places, organizations etc. It’s more common to use in the US, whereas is more common in the UK.
Python has and methods to handle this.
Example 15: Format date using strftime()
When you run the program, the output will be something like:
time: 04:34:52 s1: 12/26/2018, 04:34:52 s2: 26/12/2018, 04:34:52
Here, , , , etc. are format codes. The method takes one or more format codes and returns a formatted string based on it.
In the above program, t, s1 and s2 are strings.
- — year
- — month
- — day
- — hour [00, 01, …, 22, 23
- — minute
- — second
To learn more about and format codes, visit: Python strftime().
Example 16: strptime()
When you run the program, the output will be:
date_string = 21 June, 2018 date_object = 2018-06-21 00:00:00
The method takes two arguments:
- a string representing date and time
- format code equivalent to the first argument
By the way, , and format codes are used for day, month(full name) and year respectively.
Visit Python strptime() to learn more.
Измерение производительности небольших фрагментов кода.
Модуль предоставляет простой способ измерения времени выполнения (производительности) маленьких кусочков кода Python.
Он имеет как интерфейс командной строки, так и программный интерфейс. Это позволяет избежать ряда распространенных ловушек для измерения времени выполнения.
Примеры использования модуля :
Использование интерфейса командной строки для сравнения производительности трех различных выражений.
$ python3 -m timeit '"-".join(str(n) for n in range(100))' 10000 loops, best of 5: 30.2 usec per loop $ python3 -m timeit '"-".join()' 10000 loops, best of 5: 27.5 usec per loop $ python3 -m timeit '"-".join(map(str, range(100)))' 10000 loops, best of 5: 23.2 usec per loop
То же самое, только достигнуто с помощью интерфейса Python:
>>> import timeit >>> timeit.timeit('"-".join(str(n) for n in range(100))', number=10000) 0.3018611848820001 >>> timeit.timeit('"-".join()', number=10000) 0.2727368790656328 >>> timeit.timeit('"-".join(map(str, range(100)))', number=10000) 0.23702679807320237
Вызываемые объекты (функции, экземпляры классов и т.д.) также могут быть переданы из интерфейса Python.
>>> timeit.timeit(lambda "-".join(map(str, range(100))), number=10000) 0.19665591977536678
Обратите внимание, что функция автоматически определяет количество повторений только при использовании интерфейса командной строки. Можно предоставить оператор настройки , который выполняется только один раз в начале
Можно предоставить оператор настройки , который выполняется только один раз в начале.
Командная строка:
$ python -m timeit -s 'text = "sample string"; char = "g"' 'char in text' 5000000 loops, best of 5: .0877 usec per loop $ python -m timeit -s 'text = "sample string"; char = "g"' 'text.find(char)' 1000000 loops, best of 5: .342 usec per loop
То же самое, только программно:
>>> import timeit >>> timeit.timeit('char in text', setup='text = "sample string"; char = "g"') 0.41440500499993504 >>> timeit.timeit('text.find(char)', setup='text = "sample string"; char = "g"') 1.7246671520006203
То же самое можно сделать с помощью класса и его методов:
>>> import timeit >>> t = timeit.Timer('char in text', setup='text = "sample string"; char = "g"') >>> t.timeit() 0.3955516149999312 >>> t.repeat() #
В следующих примерах показано, как синхронизировать выражения, содержащие несколько строк. Здесь мы сравниваем стоимость использования функции и кроме проверки на отсутствие и представление атрибутов объекта.
Командная строка:
$ python -m timeit 'try:' ' str.__bool__' 'except AttributeError:' ' pass' 20000 loops, best of 5: 15.7 usec per loop $ python -m timeit 'if hasattr(str, "__bool__"): pass' 50000 loops, best of 5: 4.26 usec per loop $ python -m timeit 'try:' ' int.__bool__' 'except AttributeError:' ' pass' 200000 loops, best of 5: 1.43 usec per loop $ python -m timeit 'if hasattr(int, "__bool__"): pass' 100000 loops, best of 5: 2.23 usec per loop
То же самое, только программно:
>>> import timeit >>> # attribute is missing >>> s = """\ ... try: ... str.__bool__ ... except AttributeError: ... pass ... """ >>> timeit.timeit(stmt=s, number=100000) 0.9138244460009446 >>> s = "if hasattr(str, '__bool__'): pass" >>> timeit.timeit(stmt=s, number=100000) 0.5829014980008651 >>> >>> # attribute is present >>> s = """\ ... try: ... int.__bool__ ... except AttributeError: ... pass ... """ >>> timeit.timeit(stmt=s, number=100000) 0.04215312199994514 >>> s = "if hasattr(int, '__bool__'): pass" >>> timeit.timeit(stmt=s, number=100000) 0.08588060699912603
Чтобы предоставить модулю доступ к определенным функциям в коде, можно передать параметр настройки, который содержит оператор импорта:
def test(): """Stupid test function""" L = i for i in range(100)] if __name__ == '__main__' import timeit print(timeit.timeit("test()", setup="from __main__ import test"))
Другой вариант — передать функцию аргументу , что приведет к выполнению кода в текущем глобальном пространстве имен. Это может быть удобнее, чем указание импорта:
Python Interface¶
The module defines three convenience functions and a public class:
- (stmt=’pass’, setup=’pass’, timer=<default timer>, number=1000000, globals=None)
-
Create a instance with the given statement, setup code and
timer function and run its method with number executions.
The optional globals argument specifies a namespace in which to execute the
code.Changed in version 3.5: The optional globals parameter was added.
- (stmt=’pass’, setup=’pass’, timer=<default timer>, repeat=5, number=1000000, globals=None)
-
Create a instance with the given statement, setup code and
timer function and run its method with the given repeat
count and number executions. The optional globals argument specifies a
namespace in which to execute the code.Changed in version 3.5: The optional globals parameter was added.
Changed in version 3.7: Default value of repeat changed from 3 to 5.
- ()
-
The default timer, which is always .
Changed in version 3.3: is now the default timer.
Работа с часовыми поясами
К сожалению у меня нет большого опыта работы с часовыми поясами и примеры ниже не стоит рассматривать как лучшие практики.
Библиотека datetime не хранит часовые пояса, данные о переводах часов (летнее и зимнее время) и високосных секундах. К тому же, некоторые страны, могут изменить время опираясь на локальные ситуации. Эти ситуации опасны, когда идет запись в базу данных. Для вывода в GUI, можно использовать datetime.datetime.now() или высчитывать часовой пояс из базы.
Для записи в базу данных мы можем использовать время UTC и отдельно считать часовой пояс:
Следующий пример вычислит разницу времени между UTC и локальным. Насколько я знаю он может не сработать на версиях Python < 3.3:
Для вычисления других часовых поясов можно использовать стороннюю библиотеку pytz, которая их хранит:
Вывести все часовые пояса мы можем так:
На примере ниже я перевожу локальное время в часовой пояс Киева:
Теги:
#python
#datetime
Отличия и особенности
JavaScript прекрасен тем, что его можно запустить в консоли любого современного браузера. Это для него родная среда, и JS легко работает со страницами, объектами на ней, вкладками браузера и всем, что с ним связано.
Python — более универсальный язык, который работает не только с браузерами, поэтому для него нужен отдельный интерпретатор. Интерпретатор — это программа, которая берёт исходный код и выполняет команду за командой. Вы можете написать отличный код, но чтобы его исполнить, вам всегда нужен будет интерпретатор.
Есть два способа запустить Python-код:
1. Поставить Python себе на компьютер — этот способ хорош, если вы решили основательно изучить язык или просто любите, когда всё быстро и под контролем. Скачать Python можно с официального сайта — есть версии для всех основных операционных систем. Из минусов — нужно разбираться в параметрах установки и настройки и уметь работать с командной строкой. Плюсы — полный контроль и быстродействие.
2. Использовать онлайн-сервисы, например, этот: onlinegdb.com/online_python_compiler. Работает точно так же — пишете код, нажимаете кнопку Run и смотрите на результат.
Минусы: так как это онлайн-сервис, им пользуется одновременно много человек, поэтому быстродействия от него ждать не стоит. С подключением внешних модулей тоже могут возникнуть проблемы, но с этим можно разобраться, если потратить немного времени.
Плюс: не нужно ничего настраивать и устанавливать, всё работает сразу из браузера. Есть подсветка синтаксиса, сообщения об ошибках и возможность сохранения кода.
Сейчас мы напишем таймер с оглядкой на онлайновый сервис. А отдельно ещё расскажем об установке.
Вызов sleep() с декораторами
В некоторых случаях нужно повторно запустить неудачно выполненную в первый раз функцию. Зачастую это происходит, когда требуется повторить загрузку файла ввиду ранней перегрузки сервера. Как правило, никто не хочет делать частые запросы на серверы, поэтому добавление в Python вызова между каждым запросом предпочтительно.
Другим возможным случаем использования является необходимость проверки состояния пользовательского интерфейса во время автоматического теста. В зависимости от компьютера, на котором запускается тест, пользовательский интерфейс может грузиться быстрее или медленнее обычного. Это может изменить отображаемое на экране во время проверки программой чего-то.
В данном случае можно указать программе, чтобы та погрузилась в сон на мгновенье и затем проверить все опять через несколько секунд. Это может означать разницу между прохождением или провалом теста.
Для добавления системного вызова в Python можно использовать декоратор в каждом из данных случаев. Разберем следующий пример:
Python
import time
import urllib.request
import urllib.error
def sleep(timeout, retry=3):
def the_real_decorator(function):
def wrapper(*args, **kwargs):
retries = 0
while retries < retry:
try:
value = function(*args, **kwargs)
if value is None:
return
except:
print(f’Сон на {timeout} секунд’)
time.sleep(timeout)
retries += 1
return wrapper
return the_real_decorator
1 |
importtime importurllib.request importurllib.error defsleep(timeout,retry=3) defthe_real_decorator(function) defwrapper(*args,**kwargs) retries= whileretries<retry try value=function(*args,**kwargs) ifvalue isNone return except print(f’Сон на {timeout} секунд’) time.sleep(timeout) retries+=1 returnwrapper returnthe_real_decorator |
является вашим декоратором. Он принимает значение и количество раз для повтора , что по умолчанию равняется 3. Внутри есть другая функция, , которая принимает декорируемую функцию.
В конечном итоге самая внутренняя функция принимает аргументы и ключевые слова, которые вы передаете декорируемой функции. Здесь все и происходит! Используется , чтобы повторить вызов функции. Если возникла ошибка, вызывается , увеличивается счетчик попыток и повторяется попытка запуска функции.
Теперь переписывается для использования нового декоратора:
Python
@sleep(3)
def uptime_bot(url):
try:
conn = urllib.request.urlopen(url)
except urllib.error.HTTPError as e:
# Отправка admin / log
print(f’HTTPError: {e.code} для {url}’)
# Повторное поднятие ошибки исключения для декоратора
raise urllib.error.HTTPError
except urllib.error.URLError as e:
# Отправка admin / log
print(f’URLError: {e.code} для {url}’)
# Повторное поднятие ошибки исключения для декоратора
raise urllib.error.URLError
else:
# Сайт поднят
print(f'{url} поднят’)
if __name__ == ‘__main__’:
url = ‘http://www.google.com/py’
uptime_bot(url)
2 |
defuptime_bot(url) try conn=urllib.request.urlopen(url) excepturllib.error.HTTPError ase # Отправка admin / log print(f’HTTPError: {e.code} для {url}’) # Повторное поднятие ошибки исключения для декоратора raiseurllib.error.HTTPError excepturllib.error.URLError ase # Отправка admin / log print(f’URLError: {e.code} для {url}’) # Повторное поднятие ошибки исключения для декоратора raiseurllib.error.URLError else # Сайт поднят print(f'{url} поднят’) if__name__==’__main__’ url=’http://www.google.com/py’ uptime_bot(url) |
Здесь вы декорируете с помощью в 3 секунды. Вы также удалили оригинальный цикл и старый вызов . Декоратор теперь позаботится об этом.
Другое изменение состоит в добавлении внутри блоков, отвечающих за обработку исключений. Это нужно для правильной работы декоратора. Можно также написать декоратор, чтобы он отвечал за ошибки, однако ввиду того, что исключения касаются только , может быть лучше сохранить декоратор в текущем состоянии. В таком случае он будет работать c более широким ассортиментом функций.
Декоратору можно добавить несколько улучшений. Если число попыток заканчивается, и он по-прежнему проваливается, тогда можно сделать так, чтобы он повторно вызвал последнюю ошибку. Декоратор подождет 3 секунды после последней неудачи, что не всегда нужно. Можете попробовать поэкспериментировать самостоятельно.