4

我有一个脚本在调用时连续运行,每 5 分钟检查一次我的 gmail 收件箱。为了让它每 5 分钟运行一次,我使用了 time.sleep() 函数。但是,我希望用户在我按下 q 的任何时候结束脚本,这在使用 time.sleep() 时似乎无法完成。关于我如何做到这一点的任何建议?

阿里

4

3 回答 3

3

您可以在 sys.stdin 上使用select()并结合超时。粗略地说,您的主循环将如下所示(未经测试):

while True:
    r,w,e = select.select([sys.stdin], [], [], 600)
    if sys.stdin in r: # data available on sys.stdin
        if sys.stdin.read() == 'q':
            break
    # do gmail stuff

为了能够从标准输入读取单个字符,您需要将标准输入置于无缓冲模式。此处描述了一种替代方法。如果您想保持简单,只需要求用户在“q”后按回车键

我之前提到的 -u 标志不起作用:它可能会将 pyton 置于无缓冲模式,但不会将您的终端置于无缓冲模式。

或者,ncursus 在这里可能会有所帮助。我只是在暗示,我对此没有太多经验;如果我想要一个花哨的用户界面,我会使用 TkInter。

于 2010-10-01T07:40:39.263 回答
1

好的。试试这个 python 代码......(在 linux 中测试。很可能不会在 Windows 上工作 - 感谢 Aaron 的输入)

这是从http://code.activestate.com/recipes/572182-how-to-implement-kbhit-on-linux/派生(复制和修改)的


import sys, termios, atexit
from select import select

delay = 1 # in seconds - change this for your needs

# save the terminal settings
fd = sys.stdin.fileno()
new_term = termios.tcgetattr(fd)
old_term = termios.tcgetattr(fd)

# new terminal setting unbuffered
new_term[3] = (new_term[3] & ~termios.ICANON & ~termios.ECHO)

# switch to normal terminal
def set_normal_term():
    termios.tcsetattr(fd, termios.TCSAFLUSH, old_term)

# switch to unbuffered terminal
def set_curses_term():
    termios.tcsetattr(fd, termios.TCSAFLUSH, new_term)

def getch():
    return sys.stdin.read(1)

def kbhit():
    dr,dw,de = select([sys.stdin], [], [], delay)
    return dr <> []

def check_mail():
    print 'Checking mail'

if __name__ == '__main__':
    atexit.register(set_normal_term)
    set_curses_term()

    while 1:
        if kbhit():
            ch = getch()
            break
        check_mail()

    print 'done'
于 2010-10-01T08:04:15.523 回答
0

如果您真的想要(并且想要浪费大量资源),您可以将循环切成 200 毫秒的块。所以睡 200 毫秒,检查输入,重复直到五分钟,然后检查你的收件箱。不过,我不会推荐它。

但是,当它处于睡眠状态时,该进程被阻塞并且在睡眠结束之前不会接收输入。

哦,作为补充说明,如果你在它睡眠时按下键,它仍然应该进入缓冲区,所以当睡眠结束并最终读取输入时,它会被拉出,IIRC。

于 2010-10-01T04:59:39.300 回答