python中的连续循环和退出

发布于 2024-09-25 15:34:45 字数 159 浏览 9 评论 0原文

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

阿里

I have a script that runs continuously when invoked and every 5 minutes checks my gmail inbox. To get it to run every 5 minutes I am using the time.sleep() function. However I would like user to end the script anytime my pressing q, which it seems cant be done when using time.sleep(). Any suggestions on how i can do this?

Ali

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

你的背包 2024-10-02 15:34:45

您可以在 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 置于无缓冲模式。 此处描述了一种替代方案。如果你想让事情变得简单,只需要求用户在“q”后按 Enter 键

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

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

You can use select() on sys.stdin combined with a timeout. Roughly speaking, your main loop will look like this (untested):

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

To be able to read a single character from stdin you will need to put stdin in unbuffered mode. An alternative is described here. If you want to keep things simple, just require the user to hit enter after the 'q'

The -u flag I mentioned earlier won't work: it may put pyton in unbuffered mode but not your terminal.

Alternatively, ncursus may be of help here. I'm merely hinting, I don't have much experience with this; if I want a fancy user interface, I'd use TkInter.

放血 2024-10-02 15:34:45

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

这是从 http://code.activestate.com/recipes/572182-how-to-implement-kbhit-on-linux/< /a>


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'

Ok. try this python code... (Tested in linux. Most probably wont work on Windows - thanks to Aaron's input on that)

This is derived (copied and modified) from 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'
没︽人懂的悲伤 2024-10-02 15:34:45

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

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

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

If you really wanted to (and wanted to waste a lot of resources), you could cut your loop into 200 ms chunks. So sleep 200 ms, check input, repeat until five minutes elapse, and then check your inbox. I wouldn't recommend it, though.

While it's sleeping, though, the process is blocked and won't receive input until the sleep ends.

Oh, as an added note, if you hit the key while it's sleeping, it should still go into the buffer, so it'll get pulled out when the sleep ends and input is finally read, IIRC.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文