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