安排代码在以后的某个时间执行

时间:2016-12-31 19:01:12

标签: python macos python-2.x

如何安排某些代码在稍后的某个时间执行?

我试过了:

import time
import datetime

time.sleep(420)
print(datetime.datetime.now())

但如果Mac进入睡眠状态,则无效。

为了澄清,我需要一个脚本(好吧,一些python函数,我可以把它放到一个单独的脚本中),以便在将来的某个精确时间运行。

time.sleep无法满足我的需求,因为如果计算机在time.sleep超时期间休​​眠,则实时延迟比传递给time.sleep的延迟要长得多。例如,我在time.sleep的12:00开始延迟7分钟。然后我关上我的macbook盖子。在12:07打开它,但超时尚未完成。事实上,我必须等到大约12:13才能完成超时,尽管最初我希望我的脚本的其余部分在12:07继续。

因此,我不需要它在计算机休眠时运行,而是任何睡眠计算机都不应该影响它运行的时间。

4 个答案:

答案 0 :(得分:0)

sched模块是一个通常有用的事件调度程序。它可以通过相对(enter方法)或绝对时间(enterabs方法)优先安排事件。

由于time.sleep在Linux上使用select系统调用引入了延迟,我们必须根据time.time定义一个睡眠函数,它不会受到不必要的延迟的影响。

from __future__ import print_function
import sched
from datetime import datetime
from time import sleep, time

def my_sleep(n):
    s = time()
    while (time() - s) < n:
        # introduce small delay for optimization
        sleep(0.1)

schedule = sched.scheduler(time, my_sleep)
schedule.enter(2, 0, lambda: print(datetime.now()), ())
schedule.enter(3, 0, lambda: print(datetime.now()), ())
schedule.run()

答案 1 :(得分:0)

您最好的选择是使用cron或Apple的launchd。因为你想要在从睡眠状态唤醒后没有延迟的情况下按照设定的间隔执行任何操作,这就是我的建议。

Cron方法

要设置新的cron作业,您可以打开终端并使用您想要执行的时间信息和脚本对其进行编辑(例如,每7分钟一次):

$ crontab -e

*/7 * * * * /usr/bin/python /path/to/myscript.py

以下是对含义的快速细分:

* * * * *  command to execute
│ │ │ │ │
│ │ │ │ └─── day of week (0 - 6) (0 to 6 are Sunday to Saturday, or use names; 7 is Sunday, the same as 0)
│ │ │ └──────── month (1 - 12)
│ │ └───────────── day of month (1 - 31)
│ └────────────────── hour (0 - 23)
└─────────────────────── min (0 - 59)

列出您在crontab中设置的作业:

$ crontab -l

使用launchd定时作业

Apple建议不要使用crontab,而应使用launchd。基本上这需要创建一个首选项列表,其中包含有关您的任务的信息以及运行它的时间等。

$ cd $HOME/Library/LaunchAgents
$ nano com.username.mytask.plist

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
  "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>Label</key>
    <string>com.username.mytask</string>
    <key>ProgramArguments</key>
    <array>
        <string>/path/to/myscript.sh</string>
    </array>
    <key>StartInterval</key>
    <integer>7</integer>
    <key>RunAtLoad</key>
    <true/>
</dict>
</plist>

在纳米按控制 + O 后跟 Control + X 进行保存。

$ chmod +x /path/to/myscript.sh
$ launchctl load com.username.mytask.plist
$ launchctl start com.username.mytask.plist

以下内容将使您的脚本可执行,然后加载并启动启动代理。

停止和卸载:

$ launchctl stop com.username.mytask.plist
$ launchctl unload com.username.mytask.plist

更多信息:

Scheduling Timed JobsCreating a launchd Property List File

睡觉和关机的影响

  

如果系统关闭或处于睡眠状态,则cron作业不会执行;他们   在下一个指定时间发生之前不会运行。

     

如果通过设置StartCalendarInterval键来安排启动作业   如果工作应该运行,计算机就会睡着,你的工作就会   在电脑醒来时运行。但是,如果机器关闭时   作业应该运行,作业直到下一个才会执行   指定的时间发生。

     

关闭计算机或跳过计算机时,将跳过所有其他启动的作业   睡着了;它们不会在下一个指定时间出现之前运行。

     

因此,如果计划在计划的工作中总是关闭   时间,cron工作和启动工作都没有运行。例如,如果你   总是在晚上关闭你的电脑,一份工作计划在1点运行   上午。将永远不会被运行。

答案 2 :(得分:0)

EDIT
来自&#34; atrun&#34;的手册页 以root身份执行以下命令以启用atrun:

launchctl load -w /System/Library/LaunchDaemons/com.apple.atrun.plist  

然后像:

at now + 5 minutes
echo 'testing the at command' > myfile.txt
<EOD>  

请参阅&#34; at&#34;的手册页其他选择

答案 3 :(得分:0)

  

更新:User @ I'L'I指出我的代码中有错误。在复制粘贴wait_time变量时,我覆盖了seconds=中的必要timedelta,这阻止了循环退出。现在已经修复了。

您的代码会等待程序运行一段时间。根据你的问题,你真的不想那样,对吗?你实际上想要等到你的开始时间过去一定的秒数,并在他们过去后的第一次机会继续。

这样做:

from datetime import datetime
from datetime import timedelta

# Establish the start time as a static variable. Basically lock the start time in.
start_time = datetime.now()

# How long should we wait?
wait_time = 420

# What should I say while I wait?
wait_string = "Zzzzzzzzzzz"

# Loop until at least wait_time seconds have passed
while datetime.now() <= start_time + timedelta(seconds=wait_time):
    print(wait_string, end = "\r"),

print("Done waiting at:", datetime.now())