停止无限 while 循环重复调用 os.system

Stop an infinite while loop repeatedly invoking os.system

谢谢你们看到我的post。

首先,以下是我的代码:

import os

print("You can create your own message for alarm.")
user_message = input(">> ")

print("\n<< Sample alarm sound >>")

for time in range(0, 3):
    os.system('say ' + user_message) # this code makes sound.

print("\nOkay, The alarm has been set.")

"""
##### My problem is here #####
##### THIS IS NOT STOPPED #####

while True:
    try:
        os.system('say ' + user_message)
    except KeyboardInterrupt:
        print("Alarm stopped")
        exit(0)
"""

我的问题是 Ctrl + C 不起作用!

我尝试改变 try 块的位置,并制作信号(SIGINT)捕捉功能。

但那些也不起作用。

我已经看到 , ,以及其他几个关于这个问题的答案。

我正在使用 MAC OS(10.12.3) 和 python 3.5.2.

也赶上"SystemExit"

except (KeyboardInterrupt, SystemExit):
    print("Alarm stopped")

这是预期的行为,因为 os.system() 是 C 函数 system() 的薄包装。如 man page 中所述,父进程 在命令执行期间忽略 SIGINT。为了退出循环,你必须手动检查子进程的退出代码(这在手册页中也有提及):

import os
import signal

while True:
    code = os.system('sleep 1000')
    if code == signal.SIGINT:
        print('Awakened')
        break

然而,获得相同结果的首选(和更多 pythonic)方法是使用 subprocess 模块:

import subprocess

while True:
    try:
        subprocess.run(('sleep', '1000'))
    except KeyboardInterrupt:
        print('Awakened')
        break

您的代码将如下所示:

import subprocess

print("You can create your own message for alarm.")
user_message = input(">> ")

print("\n<< Sample alarm sound >>")

for time in range(0, 3):
    subprocess.run(['say', user_message]) # this code makes sound.

print("\nOkay, The alarm has been set.")

while True:
    try:
        subprocess.run(['say', user_message])
    except KeyBoardInterrupt:
        print("Alarm terminated")
        exit(0)

作为补充说明,subprocess.run() 仅在 Python 3.5+ 中可用。您可以在 Python.

的旧版本中使用 subprocess.call() to achieve the same effect

问题似乎是 Ctrl+C 被您通过 os.system 调用的子进程捕获了。这个子进程做出相应的反应,可能是终止它正在做的事情。如果是这样,os.system() 的 return 值将不为零。您可以使用它来打破 while 循环。

这是一个适用于我的示例(将 say 替换为 sleep):

import os
import sys

while True:
    try:
        if os.system('sleep 1 '):
            raise KeyboardInterrupt
    except KeyboardInterrupt:
        print("Alarm stopped")
        sys.exit(0)

如果Ctrl-C被子进程捕获,这里就是这种情况,最简单的解决办法是检查os.system()的return值。例如,在我的例子中,如果 Ctrl-C 停止它,它的 returns 值为 2,这是一个 SIGINT 代码。

import os

while True:
    r = os.system(my_job)
    if r == 2:
        print('Stopped')
        break
    elif r != 0:
        print('Some other error', r)