坐在电脑前运行程序是不错的,但在你没有直接监督时运 行程序,也是有用的。计算机的时钟可以调度程序,在特定的时间和日期运行,或定期运行。例如,程序可以每小时抓取一个网站,检查变更,或在凌晨12点你睡觉时,执行 CPU 繁忙型任务。Python 的 time 和 datetime 模块提供了这些函数。 利用 subprocess 和 threading 模块,你还可以编程按时启动其他程序,来完成你想要的操作,节省时间。
文章目录
- 1.1 time模块
- 1.1.1 time.time()模块
- 1.1.2 time.sleep()函数
- 1.2 round() 函数——控制小数点位数
- 秒表实验
- 1.3 datetime模块
- 1.4 timedelta模块
- 1.4.1 暂停程序直到指定日期
- 1.4.2 将datetime对象转换为字符串
- 1.4.3 将字符串转化为datetime()格式
- 1.5 多线程操作
- 1.5.1 向线程的目标函数传递参数
- 1.5.2 多线程引起的并发问题
1.1 time模块
time模块可以让Python程序读取计算机的本地时间,time模块的time.time()和time.sleep()是表有用的两个模块。
1.1.1 time.time()模块
Unix纪元是计算机编程中经常参考的时间,1970年1月1日0点,称为协调世界时间(UTC)。time.time()返回自那一刻所过的秒数,为一个浮点值。这个数字称为Unix纪元时间戳。
时间戳可以让你分析程序运行的时间
#python3
#calculateTime.py TODO:output the period of time
import time
def calculate():
#Calculate the time from start to end
value=1
for i in range(1,10000):
value=value+1
return value
startTime=time.time()
temp=calculate()
endTime=time.time()
print('The result is %s types long.'%(len(str(temp))))
print('Takes %s seconds to calculate.'%(endTime-startTime))
运行结果:
程序先引入time模块,然后先记录开始时间戳,然后运行程序中的自定义函数 calculate(),再记录结束时间戳,最后结束时间戳减去开始时间戳等于程序运行时间
1.1.2 time.sleep()函数
程序睡眠函数time.sleep(),通过传入参数即秒数来控制程序的暂停
新版本的Python键入Ctrl+C会马上终止,旧版本的要等到睡眠时间到了以后才能线束键入被中断
1.2 round() 函数——控制小数点位数
在处理时间戳时,为了更好的处理时间,通常采用round()函数来简化浮点值
秒表实验
我们可以写一个秒表,来记录每次开始和结束的时间,还有总时间。这种类型可以用来体育测试,记录百米赛跑的具体时间
#通过使用回车来 开始
#再按一次回车结束
#!python3
#calcuTime.py-calculate time cf circles
import time
#Display the object's details
print('Please ENTER to begin.Then,u can press ENTER more agnin to stop the calculating.Press Ctrl-C to exit')
input() #Press ENTER to begin
print('Started')
startTime=time.time() # Recorded the time for start
lastTime=startTime
circleNum=1 #circleNum为圈数
#TODO:Start tracking the circle times and every keyboard's time.
try:
while True:
input()
CirclesTime=round(time.time()-lastTime,2)
TotalTime=round(time.time()-startTime,2)
#circleNum+=1
print('Lap:%s Total:%s LapTime:%s'%(circleNum,TotalTime,CirclesTime),end='')
circleNum+=1
lastTime=time.time() #record the new time for start
except KeyboardInterrupt:
#Handle the Ctrl-C exception to stop error messages displaying
print('Calculate time for circles has done')
为了避免程序运行出错,我们将程序的循环执行部分放入try语句中,一旦使用Ctrl-C来暂停,进入except语句不会出现错误提示,而是输出计算时间已结束(格式为except+错误信息:)
结果图:
1.3 datetime模块
datetime模块可以取得现在的时间以及UTC时间,而不是Unix时间戳,还可以单独显示当前的年月日,而且还可以推断在Unix纪元时间以后的多少秒后的现实时间,返回的数字分别为年 月 日 时 分 秒 微妙(浮点值)
fromtimestamp()函数传入一个时间参数后返回的为计算后的时间,距离Unix纪元时间的秒数所对应的时间,utcnow()函数为utc时间,即协调世界时间
datetime对象之间还可以进行比较,通过查看逻辑值
1.4 timedelta模块
timedelta模块提供时间段而不是一个时刻。
要创建 timedelta 对象,就要用 datetime.timedelta()函数。datetime.timedelta()函数接受关键字参数 weeks、days、hours、minutes、seconds、milliseconds 和 microseconds。 没有 month 和 year 关键字参数,因为“月”和“年”是可变的时间,依赖于特定月份或年份。timedelta 对象拥有的总时间以天、秒、微秒来表示。这些数字分别保存 在 days、seconds 和 microseconds 属性中。total_seconds()方法返回只以秒表示的时 间。将一个 timedelta 对象传入 str(),将返回可读性更好的日期形式。
- 算术运算符可以对datetime对象所代表的值进行运算,这比自己手算要快的多,如果天数是好几年的话,需要记住每个月是否为30天或者31天以及平年或是闰年
用乘法来做datetime对象的加减
3
timedelta对象只是一个日期类的对象,并不是一个真正的数字变量,所以不能用于在timedelta()里面做算术运算,斗则会报错,不支持的类型
1.4.1 暂停程序直到指定日期
变量要以字母开头,不能以数字开头,此程序利用一个while 循环和time.sleep()函数来达到暂停的目的
#!python3
#cutTime-stop yhe process to the pointed date
import datetime
import time
NationalDayOf2020=datetime.datetime(2020,10,1,0,0,0)
while datetime.datetime.now()<NationalDayOf2020:
time.sleep(1)
1.4.2 将datetime对象转换为字符串
Unix纪元戳和datetime对象都不是友好的可读对象。利用 strftime()方法,可以将 datetime 对象显示为字符串。(strftime()函数名中的f 表示格式,format)。
%Y | 带世纪的年份,例如‘2020‘’’ |
%y | 不带世纪的年份,‘00‘-’99’(1970-2069,从Unix纪元年开始) |
%m | 数字表示的月份,‘01’-‘12’ |
%B | 完整的月份,例如‘September’ |
%b | 简写的月份,比如‘Sep’ |
%j | 一年中的第几天,‘001’至‘366’ |
%d | 一月中的第几天,‘01’至‘31’ |
%w | 一周中的第几天 ,‘0’至‘6’,星期一至星期日 |
%A | 完整的周几,比如‘Monday’ |
%a | 简写的周几,比如‘Tue’ |
%H | 小时,24小时制,从‘00’至‘23’ |
%I | 小时,12小时制,从‘01’至‘12’ |
%M | 分,‘00’至‘59’ |
%S | 秒,‘00’至‘59’ |
%p | ‘AM’或“PM” |
%% | %字符 |
向strftime()传入指定的参数,比如格式化字符以及斜杠,冒号等等,strftime()方法将传回一个对应的格式化数据
1.4.3 将字符串转化为datetime()格式
将字符串转化为datetime格式需要strptime()函数
必须严格匹配所对应的日期格式,这样才不会出错
1.5 多线程操作
多线程从名称上来看即多个线程进行工作。什么是线程?线程的定义为CPU分配的最小单位,不分配系统资源,多个线程可共享一个进程所分配的其它硬件资源。线程为轻量化级操作,减轻了CPU的开销,不必来回撤销所分配给进程的资源,共享进程的资源即可,对CPU没有什么要求,线程即软件层面实现的虚拟处理器。利用分时系统等可实现并发执行。并发为在同一时间段内发生,并行意为在同一时刻发生,对处理器有需求,需要多核处理器。
下面的代码即程序需要等到while循环执行完以后才可以执行print函数。而多线程则不需要,可同时执行不同的代码块,执行效率会高很多,对CPU的利用率也高。
#!python3
#cutTime-stop yhe process to the pointed date
import datetime
import time
NationalDayOf2020=datetime.datetime(2020,10,1,0,0,0)
while datetime.datetime.now()<NationalDayOf2020:
time.sleep(1)
print('It has done')
要想实现多线程操作,可以使用Python的threading模块,来安排一个新线程做它原本的工作,原来的线程可以继续执行其它的工作,比如print函数,而新线程继续执行上面休眠代码块。
#!python3
#multithreading.py-To start another new threading
import threading,time
print('Start this subject.')
def takeThread():
time.sleep(3)
print('The thread was waked up.')
newThread=threading.Thread(target=takeThread)
newThread.start()
print('The process has complished.')
在上面的代码中,我们创建了一个thread对象。利用函数threading.Thread()创建一个新的线程,并传入参数target=takeThread函数,此处传入的并不是takeThread(),目的不在于调用这个函数并返回它的值作为参数,而是创建一个执行这个作为参数的函数的新线程。所以会出现下图的先出现原先的线程执行的print函数所输出的 The process hascomplished,后出现新的线程转而去执行takeThread()函数,因为有睡眠函数,所以后出现。
效果图:
下面的函数则会直接输出,因为没有睡眠函数
#!python3
#multithreading.py-To start another new threading
import threading,time
print('Start this subject.')
def takeThread():
#time.sleep(3)
print('The thread was waked up.\n')
newThread=threading.Thread(target=takeThread)
newThread.start()
print('The process has complished.')
1.5.1 向线程的目标函数传递参数
通过import关键字引入threading线程模块,向args传入常规参数(Apple、Orange,Banana),向kwargs传入关键字参数分隔符sep,关键字参数可以作为字典的形式来提供给kwargs
如果按照下面的格式来传入参数的话,直接调用的是print函数,而不是将它作为一个参数传递给threading,Thread()函数,不需要开启新线程便直接输出。
1.5.2 多线程引起的并发问题
多线程提升处理器的效率时,同时也可能引发一系列不好的后果,并发可能并不具有异步性,即按照不同的时刻,只要处理步骤相同,就可得到相同的后果。可能导致变量的不恰当引用而导致发生不可逆转的错误,致使程序发生不进入人意的后果。
为了避免并发问题,绝不让多个线程读取或写入相同的变量。当创建一个新的Thread对象时, 要确保其目标函数只使用该函数中的局部变量。这将避免程序中难以调试的并发问题。