接上文 Python模块操作:time—Clock Time(一)https://developer.aliyun.com/article/1618983
处理器时钟时间
当time()函数返回一个挂钟时间,process_time()函数返回处理器时钟时间。这个来自process_time()函数的返回值反应的是当程序运行时使用的实际时间。
import hashlib
import time
# data用来计算md5校验和
data = open(__file__, 'rb').read()
for i in range(5):
h = hashlib.sha1()
print(time.ctime(), ': {:0.3f} {:0.3f}'.format(time.time(),
time.process_time()))
for i in range(300000):
h.update(data)
cksum = h.digest()
本示例中,格式化的ctime()与来自time()和clock()函数每次循环迭代的浮点值也一起被打印出来。
mac OS系统运行结果如下:
Sat Dec 24 15:34:24 2022 : 1671867264.858 0.851
Sat Dec 24 15:34:25 2022 : 1671867265.055 1.043
Sat Dec 24 15:34:25 2022 : 1671867265.258 1.241
Sat Dec 24 15:34:25 2022 : 1671867265.449 1.428
Sat Dec 24 15:34:25 2022 : 1671867265.629 1.607
注意
如果您希望在您的系统上运行这个示例,您可能必须向内循环添加更多的循环,或者处理更大量的数据,才能真正看到时间上的差异。
通常,如果程序不执行任何操作,处理器时钟就不会滴答作响。
import time
template = '{} - {:0.2f} - {:0.2f}'
print(template.format(
time.ctime(), time.time(), time.process_time()
))
for i in range(3, 0, -1):
print('Sleeping', i)
time.sleep(i)
print(template.format(
time.ctime(), time.time(), time.process_time()
))
在本例中,循环在每次迭代之后进入睡眠状态,只做很少工作。即使应用程序进入休眠状态,time()值也会增加,但process_time()值不会。macOS系统运行结果如下:
Sat Dec 24 15:54:31 2022 - 1671868471.45 - 0.81
Sleeping 3
Sat Dec 24 15:54:34 2022 - 1671868474.45 - 0.81
Sleeping 2
Sat Dec 24 15:54:36 2022 - 1671868476.45 - 0.81
Sleeping 1
Sat Dec 24 15:54:37 2022 - 1671868477.46 - 0.81
调用sleep()函数会释放当前线程的控制权,并要求它等待系统将其唤醒。如果一个程序只有一个线程,这有效地阻塞了app而且它不工作。
性能计数器
有一个高解析度的单调时钟来测量性能是很重要的。确定最佳时钟数据源需要特定平台知识,Python在perf_counter()函数里提供了这些。
import hashlib
import time
# data用于计算md5校验和
data = open(__file__, 'rb').read()
loop_start = time.perf_counter()
for i in range(5):
iter_start = time.perf_counter()
h = hashlib.sha1()
for i in range(300000):
h.update(data)
cksum = h.digest()
now = time.perf_counter()
loop_elapsed = now - loop_start
iter_elapsed = now - iter_start
print(time.ctime(), ': {:0.3f} {:0.3f}'.format(
iter_elapsed, loop_elapsed
))
与monotonic()函数一样,perf_counter()的纪元是未定义的,这些值将用于比较和计算值,而不是绝对的时间。
macOS系统运行结果如下:
Sat Dec 24 16:12:45 2022 : 0.221 0.221
Sat Dec 24 16:12:45 2022 : 0.240 0.461
Sat Dec 24 16:12:45 2022 : 0.199 0.660
Sat Dec 24 16:12:45 2022 : 0.219 0.879
Sat Dec 24 16:12:45 2022 : 0.221 1.100
时间组件
时间存储为经过的秒数在某些场合是有用的,但是有时候程序需要获取日期的各个字段(年,月等)。time模块定义了struct_time 用于保存日期和时间值,并将组建分开,便于访问。有几个函数用结构时间值而不是浮点数。
import time
def show_struct(s):
print(' tm_year :', s.tm_year)
print(' tm_mon :', s.tm_mon)
print(' tm_mday :', s.tm_mday)
print(' tm_hour :', s.tm_hour)
print(' tm_min :', s.tm_min)
print(' tm_sec :', s.tm_sec)
print(' tm_wday :', s.tm_wday)
print(' tm_yday :', s.tm_yday)
print(' tm_isdst:', s.tm_isdst)
print('gmtime:')
show_struct(time.gmtime())
print('\nlocaltime:')
show_struct(time.localtime())
print('\nmktime:', time.mktime(time.localtime()))
这个gmtime()函数返回当前UTC时间。localtime()返回当前应用的时区的当前时间。mktime()接受一个struct_time并且转换成浮点型表示。
macOS系统运行结果如下:
gmtime:
tm_year : 2022
tm_mon : 12
tm_mday : 24
tm_hour : 9
tm_min : 0
tm_sec : 16
tm_wday : 5
tm_yday : 358
tm_isdst: 0
localtime:
tm_year : 2022
tm_mon : 12
tm_mday : 24
tm_hour : 17
tm_min : 0
tm_sec : 16
tm_wday : 5
tm_yday : 358
tm_isdst: 0
mktime: 1671872416.0
使用时区
确定当前时间的函数依赖于通过程序或使用系统的默认时区设置时区。更改时区并不会改变实际时间,只会改变表时间的方式。要更改时区,请设置环境变量TZ,然后调用tzset()函数。可以通过许多细节指定时区,精确到夏令时的开始和停止时间。不过,使用时区名称并让底层库派生其他信息通常更容易。
这个示例将时区更改为几个不同的值,并显示这些更改如何影响时间模块中的其他设置。
import time
import os
def show_zone_info():
print(' TZ :', os.environ.get('TZ', '(not set)'))
print(' tzname:', time.tzname)
print(' Zone : {} ({})'.format(
time.timezone, (time.timezone / 3600)
))
print(' DST :', time.daylight)
print(' Time :', time.ctime())
print()
print('Default:')
show_zone_info()
ZONES = [
'GMT',
'Europe/Amsterdam',
]
for zone in ZONES:
os.environ['TZ'] = zone
time.tzset()
print(zone, ':')
show_zone_info()
系统用于准备示例的默认时区是CST。示例中的其他区域更改tzname,日光标志和时区偏移值。
在macOS系统运行结果如下:
Default:
TZ : (not set)
tzname: ('CST', 'CST')
Zone : -28800 (-8.0)
DST : 0
Time : Sat Dec 24 17:44:57 2022
GMT :
TZ : GMT
tzname: ('GMT', 'GMT')
Zone : 0 (0.0)
DST : 0
Time : Sat Dec 24 09:44:57 2022
Europe/Amsterdam :
TZ : Europe/Amsterdam
tzname: ('CET', 'CEST')
Zone : -3600 (-1.0)
DST : 1
Time : Sat Dec 24 10:44:57 2022
解析和格式化时间
两个函数strptime()和strftime()在时间值的结构时间和字符表示之间进行转换。有一个很长的格式说明列表,用于支持不同样式的输入和输出。完整的列表记录在time模块的库文档中。
此示例将当前时间从字符串转换为struct时间实例,然后再转换回字符串。
import time
def show_struct(s):
print(' tm_year :', s.tm_year)
print(' tm_mon :', s.tm_mon)
print(' tm_mday :', s.tm_mday)
print(' tm_hour :', s.tm_hour)
print(' tm_min :', s.tm_min)
print(' tm_sec :', s.tm_sec)
print(' tm_wday :', s.tm_wday)
print(' tm_yday :', s.tm_yday)
print(' tm_isdst :', s.tm_isdst)
now = time.ctime(1383391847.433716)
print('Now: ', now)
parsed = time.strptime(now)
print('\nParsed:')
show_struct(parsed)
print('\nFormatted:',
time.strftime('%a %b %d %H:%M:%S %Y', parsed))
输出字符串与输入不完全相同,因为月份的日期前缀是0
macOS系统输出结果如下:
Now: Sat Nov 2 19:30:47 2013
Parsed:
tm_year : 2013
tm_mon : 11
tm_mday : 2
tm_hour : 19
tm_min : 30
tm_sec : 47
tm_wday : 5
tm_yday : 306
tm_isdst : -1
Formatted: Sat Nov 02 19:30:47 2013