我有一个脚本,在调用时连续运行,每5分钟检查一次我的Gmail收件箱。为了让它每5分钟运行一次,我使用的是time.sleep()函数。但是我希望用户在按下q时随时结束脚本,这在使用time.sleep()时似乎无法完成。关于我如何做到这一点的任何建议?
阿里
答案 0 :(得分: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
为了能够从stdin读取单个字符,您需要将stdin置于无缓冲模式。另一种描述是here。如果你想保持简单,只需要用户在'q'
之后按Enter键我之前提到的-u标志不起作用:它可能将pyton置于无缓冲模式但不是终端。
或者,ncursus在这里可能会有所帮助。我只是暗示,我对此没有多少经验;如果我想要一个精美的用户界面,我会使用TkInter。
答案 1 :(得分: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'
答案 2 :(得分:0)
如果你真的想(并且想浪费大量资源),你可以将你的循环切成200毫秒的块。所以睡200毫秒,检查输入,重复直到五分钟,然后检查你的收件箱。不过我不推荐它。
虽然它正在睡觉,但是过程被阻止,并且在睡眠结束之前不会接收输入。
哦,作为一个补充说明,如果你在键睡觉时按下键,它仍应进入缓冲区,因此当睡眠结束并最终读取输入时,它将被拉出,IIRC。