我在做一个闹钟,等到谋个时间就开始执行谋个动作(在下面的案例里面简化为 print('ok'))。请问这是否是最佳办法?因为我担心会不会导致占用内存过高等问题。我看有一个叫 alarm 的库,也是用 while 循环等待时间。以下是我的示例代码:
在 2020 年 10 月 17 日 10 点 50 分 50 秒的时候触发事件 print('ok')
from datetime import datetime
def alarm():
	while True:
		now = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
		if now == '2020-10-17 10:50:50':
			print('ok')
			break
if __name__ == '__main__':
	alarm()
感谢大家的回复!根据大家的建议和帮助,我决定采用计算时间差然后用sleep的办法。其他办法比如用第三方库或者线程等方法也很好,但我希望尽量简单点。这个只需要精确到未来某个时间的秒即可。我更新代码如下,希望对其他新手有帮助:
from time import sleep
from datetime import datetime
def alarm():
	now = datetime.now().timestamp()
	set_time = datetime(2020, 10, 16, 22, 42, 50).timestamp()
	delta = set_time - now
	sleep(delta)
	print('ok')
if __name__ == '__main__':
	alarm()
|  |      1duyuyouci      2020-10-16 11:20:41 +08:00 可以用 celery 做定时任务啊 | 
|  |      2ruanimal      2020-10-16 11:25:12 +08:00  3 循环里加个 sleep 吧,不然 cpu 都占满了 | 
|  |      3nevin47      2020-10-16 11:25:52 +08:00 CPU 都炸了。。。。。。 | 
|  |      4RRRoger      2020-10-16 11:26:23 +08:00 用操作系统的定时任务触发是不是会更好点 | 
|  |      5vZexc0m      2020-10-16 11:26:49 +08:00  4 可以用 APScheduler | 
|      6yaoye555      2020-10-16 11:27:59 +08:00  1 crontab 或许更值得拥有 | 
|      7qile1      2020-10-16 11:29:44 +08:00 via Android 这样应该可以,但是有时候 print 有数据,程序确不执行挺奇怪,好像也没有啥好办法 | 
|  |      8ysc3839      2020-10-16 11:31:12 +08:00  1 内存占用不高,CPU 使用率会高。如果不想使用操作系统独有的 API 的话,那就加上 sleep 吧。 | 
|  |      9no1xsyzy      2020-10-16 11:31:46 +08:00 占满一个核,内存不会泄漏 不要用等于判断时间 | 
|  |      10stephenxiaxy      2020-10-16 11:32:09 +08:00 。。。 | 
|  |      11MoYi123      2020-10-16 11:50:30 +08:00  1 不如 asyncio.sleep | 
|  |      12MagnifierSun      2020-10-16 12:56:12 +08:00  1 ??? 你知道这个语句一秒钟要执行多少遍吗哈哈哈 有个 Schedule 的库,自己去搜搜 | 
|      13Chenamy2017      2020-10-16 13:25:49 +08:00  2 加 sleep 即可,时间也不要用==,超过这个时间后就执行动作。 | 
|  |      14Sapp      2020-10-16 13:34:45 +08:00 你这个时间必出坑... | 
|  |      15kimqcn      2020-10-16 13:37:19 +08:00 谁把我的代码偷出来了呵呵呵 | 
|      16Vhc001      2020-10-16 13:37:32 +08:00  6 这是我见过最坑爹的代码 | 
|      17Chaidu      2020-10-16 13:39:48 +08:00  1 建议转行 (狗头 | 
|      18Tokiomi      2020-10-16 13:43:55 +08:00 哈哈哈,学生代码吧 | 
|  |      19sudoy OP | 
|  |      20est      2020-10-16 13:46:06 +08:00  1 其实底层库就是你这样实现的。只不过加了很多东西。比如上面说的要加个 sleep(1) 这就是你最小定时精度。 | 
|      23widewing      2020-10-16 13:59:21 +08:00 via Android sleep 为什么要加在循环里?直接 sleep 指定时间不香吗? | 
|  |      24dswyzx      2020-10-16 14:02:06 +08:00 via iPhone 别听他们的,加 sleep 万一错过这个点了呢,大于等于时间万一没有拯救世界成功呢。 综上所述:能用就行! | 
|  |      25imdong      2020-10-16 14:03:15 +08:00  1 之前有过类似的需求,不过我的做法是用 sleep 但是不是 sleep(1) 而是再执行完毕后,检查距离下一次执行的时间差,然后睡眠到那个时间。 | 
|  |      26shuax      2020-10-16 14:04:56 +08:00 sleep(0)即可 | 
|  |      27est      2020-10-16 14:21:49 +08:00 @widewing  设想一个场景。你在虚拟机里跑起来了这个程序。你让虚拟机暂停了。然后 1 个小时后,恢复了虚拟机。这个时候你的 sleep 还是对的吗。 | 
|  |      28sudoy OP @est 哈哈,虽然我找半天没有找到 python 内置的 `sleep()` 是怎么写的,你的话听起来还挺鼓励人的。不过他们说这样写会导致 CUP 占用过高,可能确实没有用 sleep 好,sleep 没有这么高的 CUP 占用。 | 
|  |      29wusheng0      2020-10-16 14:24:38 +08:00 via Android 是不是 fork 一个进程后台运行更好, 有没有大佬来说一下 | 
|  |      30felixcode      2020-10-16 14:27:06 +08:00 多开几个闹钟就能把多核 CPU 占满了。 | 
|  |      32zkqiang      2020-10-16 14:48:36 +08:00 没让你 sleep 0 啊。。直接计算 定时减去现在 有多少秒,sleep 多少秒就行了 | 
|  |      34zkqiang      2020-10-16 14:56:36 +08:00  1 或者 sleep(0.5) 每半秒检查一次,另外时间不要用 == 判断,最好用区间判断允许一些误差 | 
|  |      36bruce00      2020-10-16 15:06:42 +08:00 狗头真的能保命 | 
|  |      37heyjei      2020-10-16 15:09:29 +08:00 我真的在生产环境见过这样的代码,你们应该能够理解我当时的心情。 | 
|  |      389LCRwvU14033RHJo      2020-10-16 15:13:02 +08:00  2 sleep(0)真实绝了。 | 
|  |      40Norie      2020-10-16 15:17:51 +08:00 via iPhone 这是 CPU 性能测试 | 
|      41fuchunliu      2020-10-16 15:29:58 +08:00 via Android 你是对的,他要听他们的,不然别人说你跑的假程序,CPU 都没占用 | 
|  |      42ysc3839      2020-10-16 15:37:40 +08:00  1 @est Windows 有 SetThreadpoolTimer,这个可以设置绝对时间,不受睡眠影响,还可以设置允许系统推迟执行,相比 sleep 更加省电。 | 
|  |      43winglight2016      2020-10-16 15:38:58 +08:00 @heyjei 这样的生产环境还能有任何“生产”吗?🐶 | 
|  |      44Bijiabo      2020-10-16 15:40:28 +08:00 看到 sleep(0) 笑死我了哈哈哈 | 
|      45lazyfighter      2020-10-16 15:40:29 +08:00 既然 sleep,为什么不算一下 sleep 多长时间呢 | 
|  |      46ThisQ      2020-10-16 15:41:06 +08:00 用系统定时任务调用脚本执行呢? | 
|  |      47ysc3839      2020-10-16 15:45:23 +08:00  1 @wusheng0 我一般会选择用新线程来后台执行,fork 在某些操作系统上有坑,比如 Windows 没有 fork,macOS fork 之后不 exec 没法使用 CoreFoundation 。用线程的话可以共享资源,也没有那么多坑。 | 
|      48zgzb      2020-10-16 15:47:19 +08:00 via Android 我选择 after | 
|  |      49nine9      2020-10-16 15:50:45 +08:00  1 可以考虑 threading.Event() event.wait(timeout=None) event.set() 也就是 APScheduler 这个库实现使用的 | 
|  |      510bit      2020-10-16 16:01:03 +08:00  1 sleep 的问题已经很多人说了,我提一下关于时间比对的问题吧。 现在这样用 str 比对,容易有小坑,还是应该用更本质的数据去比对,比如 unix timestamp,更不容易出错。 | 
|  |      52nuk      2020-10-16 16:22:49 +08:00 最好调整成实时优先级,不然这一秒容易被跳过 | 
|  |      54DoctorCat      2020-10-16 16:33:38 +08:00  1 兼容 posix 标准的系统还可以利用系统信号:signal 、setitimer 定时器交给 OS 去做了 | 
|      55ma7x      2020-10-16 16:34:24 +08:00 win10 自带闹钟超级好用 为什么要造轮子 | 
|  |      56www5070504      2020-10-16 16:34:50 +08:00 你这种写法 每天多费半度电吧   加个 timer 之类的 sleep 都行啊 | 
|  |      57SmartKeyerror      2020-10-16 16:34:56 +08:00 单线程直接用信号不就好了,向内核注册一个定时器,定时器到期后向进程发送 SIGALRM 信号。 | 
|      58darknoll      2020-10-16 16:37:27 +08:00 传说中的忙等待自旋锁? | 
|  |      59fish267      2020-10-16 16:40:03 +08:00 还是 crontab 吧 | 
|  |      60muzuiget      2020-10-16 16:43:57 +08:00 哈哈,我也想到传说中的自旋锁。 | 
|  |      61xionger      2020-10-16 16:45:36 +08:00 哈哈 劝改行 | 
|  |      62ruanimal      2020-10-16 16:51:21 +08:00 @findlisa  每时每刻都在判断时间是否相等,也就是 cpu 一直是忙碌的状态,自然就会占满一个核心。如果有 sleep,cpu 在你程序 sleep 的期间就干别的,或者休息去了。 ps: 去看看操作系统的书,看看进程的调度。 | 
|  |      63GoLand      2020-10-16 16:52:47 +08:00 淦,这么精妙的代码我怎么想不到。 | 
|  |      64shuax      2020-10-16 16:54:46 +08:00 哎哟,我错了,sleep 0 确实不行,起码得 0.001 | 
|  |      65kiracyan      2020-10-16 16:58:28 +08:00 硬是要这么做建议你 sleep 个 300 秒  然后判断一下当前时间距离设定时间是不是小于 300 秒 再 sleep 1 秒 | 
|  |      66shenqi      2020-10-16 17:04:06 +08:00 。。。明显的实习生写的代码。 (又不是不能用.jpg ) | 
|      67Hxu2M811KVSJqN75      2020-10-16 17:06:43 +08:00 这个算今日最佳 [欢乐贴] 么? | 
|      68jimmyismagic      2020-10-16 17:12:19 +08:00  1 评论里说实习生写的代码的,自己可以写一个出来试试,看能做到多高的精度,要做到等于而不是大于等于 | 
|      70sapocaly      2020-10-16 17:21:45 +08:00 | 
|  |      71iSecret      2020-10-16 17:36:17 +08:00 用 crontab 执行任务的话没这么多蛋疼的事还可以顺道解决了可能需要重复执行的问题,非要用 py 建议 sleep(执行时间 - 当前时间)。 | 
|  |      72tabris17      2020-10-16 17:42:57 +08:00 实现了一个野生 spinning | 
|  |      73lane1      2020-10-16 17:53:00 +08:00 用术语来说, 你的写法是 spinlock, busy-waiting, CPU-bound... 不过话说计时器到底如何实现呢? | 
|  |      74Tonni      2020-10-16 17:58:12 +08:00  1 哈哈,别的不说,楼主头像的狗子好可爱🐶 | 
|  |      75UN2758      2020-10-16 18:31:52 +08:00  1 lz 这么狂野的写法,怀念当年的我,哈哈哈哈 | 
|  |      76JCZ2MkKb5S8ZX9pq      2020-10-16 18:43:57 +08:00 直接算 timestamp 的时间差,sleep 一次到底不就好了。 这个格式化时间的操作有点多余,重复计算没必要啊。 | 
|  |      77wuwukai007      2020-10-16 18:52:31 +08:00 via Android 直接计算时间差,sleep,每次激活的时候重新计算, | 
|  |      78lysS      2020-10-16 18:56:57 +08:00 想到见过 JS 延时函数: function sleepSync(ms) { var curr = new Date().getTime(); ms += curr; while (curr < ms) { curr = new Date().getTime(); } } | 
|  |      79CSM      2020-10-16 19:10:16 +08:00 via Android 直接一觉睡到目标时间,醒来后完成任务就行,循环也不用 | 
|  |      80echoick      2020-10-16 19:17:21 +08:00 via iPhone 哈哈哈哈 sleep(0) | 
|  |      81inframe      2020-10-16 20:08:47 +08:00 我真的在生产环境见过这样的代码,你们应该能够理解我当时的心情。 +1 | 
|  |      82ctro15547      2020-10-16 20:46:06 +08:00 延迟 0.1 秒就行 。。 | 
|  |      83E1n      2020-10-16 23:37:42 +08:00 via Android 哈哈加油 | 
|  |      84Yinz      2020-10-17 00:05:27 +08:00 不得不说,楼主心态蛮好的,加油,谁都有新手阶段,学习即可 | 
|  |      85by73      2020-10-17 00:11:30 +08:00 突然对 time.sleep 有了点兴趣,最后发现居然调用的是 select() 系统调用😂 | 
|  |      86irytu      2020-10-17 00:19:26 +08:00 os.sched_yield() 不过 Windows 上没有这种方法 我一般为了 portable 会写成 time.sleep(0.0001) | 
|  |      87vcfghtyjc      2020-10-17 00:25:28 +08:00  1 运行时候检测一下当前时间,然后算出需要的睡眠时间,sleep 就行了 | 
|  |      88shijingshijing      2020-10-17 00:42:59 +08:00 sleep(0)没毛病,代码不改,在 crontab 里面设定 2020 年 10 月 17 日 10 点 50 分 50 秒执行一次就 ok 了。 | 
|  |      89discrete      2020-10-17 06:22:20 +08:00 想起了 Sleep Sort. | 
|  |      92inorilzy      2020-10-17 10:03:30 +08:00 APScheduler 和 celery 都可以定时任务。 | 
|      96nuistzhou      2020-10-17 14:57:37 +08:00 via iPhone 为何我想起了大名鼎鼎的“睡眠排序法”?! | 
|      98adamwong      2020-10-17 15:52:36 +08:00 @SmartKeyerror 我怎么又抓到你了 | 
|  |      99nuk      2020-10-17 17:18:14 +08:00  1 @sudoy import win32api,win32process,win32con pid = win32api.GetCurrentProcessId() handle = win32api.OpenProcess(win32con.PROCESS_ALL_ACCESS, True, pid) win32process.SetPriorityClass(handle, win32process.REALTIME_PRIORITY_CLASS) | 
|  |      100IDAEngine      2020-10-17 18:48:11 +08:00 via iPhone 用系统 API 不香吗? while sleep 不靠谱 |