运行一个Python脚本,让用户指定运行时间

20

今天我刚开始学习Python。我一直在阅读《Byte of Python》。现在我有一个涉及时间的Python项目。我在《Byte of Python》中找不到任何与时间有关的内容,因此我想请问:

如何运行用户指定的一段时间并在运行结束后停止代码块?

例如(伪代码):

time = int(raw_input('Enter the amount of seconds you want to run this: '))
while there is still time left:
    #run this block

或者更好的是:

import sys
time = sys.argv[1]
while there is still time left:
    #run this block
3个回答

26

我建议创建另一个线程,将其设置为守护线程,然后休眠直到任务结束。例如:

from time import sleep
from threading import Thread

def some_task():
    while True:
        pass

t = Thread(target=some_task)  # run the some_task function in another
                              # thread
t.daemon = True               # Python will exit when the main thread
                              # exits, even if this thread is still
                              # running
t.start()

snooziness = int(raw_input('Enter the amount of seconds you want to run this: '))
sleep(snooziness)

# Since this is the end of the script, Python will now exit.  If we
# still had any other non-daemon threads running, we wouldn't exit.
# However, since our task is a daemon thread, Python will exit even if
# it's still going.

当所有非守护线程退出时,Python解释器将会关闭。因此,当主线程退出时,如果唯一正在运行的线程是在单独的守护线程中运行的任务,那么Python将直接退出。这是一种方便的方法,如果您想要在后台运行某些任务,并且不需要手动停止它并等待它停止就可以轻松退出。
换句话说,相比使用for循环中的sleep方法,这种方法的优点在于,在该情况下,您必须将任务编写成离散块,并定期检查时间是否到期。这可能对您的目的来说是可以接受的,但它也可能存在问题,例如如果每个块都需要相当长的时间,从而导致程序运行时间显著超过用户输入的时间等。这是否对您造成问题取决于您正在编写的任务,但我想提到这种方法,以防它对您更好。

1
抱歉,您能对其中一些进行注释吗?我还没有涉足线程和睡眠。根据您的回答,我的理解是:从睡眠中唤醒会打断线程? - Rob
@Rob:我已经对代码进行了更多的解释和添加了几个注释。如果有任何不清楚的地方,请告诉我。 - Eli Courtwright
1
实际上,你已经让一切变得非常清晰了。这似乎比反复检查时间更有效率。非常感谢。 - Rob
t.start放在inputsleep语句之间,这样用户思考并输入所需时间时,守护进程就不会运行,这样会稍微好一点,不是吗? - ChrisFreeman

15

试试使用time.time(),它将返回当前时间与一个称为纪元的固定时间(对于许多计算机来说是1970年1月1日午夜)之间的秒数。以下是一种使用方法:

import time

max_time = int(raw_input('Enter the amount of seconds you want to run this: '))
start_time = time.time()  # remember when we started
while (time.time() - start_time) < max_time:
    do_stuff()

因此,只要自开始以来的时间小于用户指定的最大时间,我们就会循环执行。这并不完美:最明显的是,如果do_stuff()需要很长时间,我们将一直等到它完成并发现我们已经超过了截止时间才能停止。如果您需要在时间耗尽时立即中断正在进行的任务,问题会变得更加复杂。


我确实需要能够中断正在进行的任务。但这不是一个简单的修改吗,比如 if (time.time() - start_time) > max_time: break?如果我错了,请纠正我。 - Rob
2
当然可以!那样做很好 - 你只需要确保在执行小块代码之间运行测试即可。 - Etaoin
1
这种方法不可扩展,因为 while 条件中的开销。假设我想调用 do_Stuff n 次,使得 n >>> max_time,使用这种方法会很困难。 - user1302884

6

如果你正在使用Linux系统,想要中断一个长时间运行的进程,可以使用信号(signal)

import signal, time

def got_alarm(signum, frame):
    print 'Alarm!'

# call 'got_alarm' in two seconds:
signal.signal(signal.SIGALRM, got_alarm)
signal.alarm(2)

print 'sleeping...'
time.sleep(4)

print 'done'

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接