5 votes

Arrêter une boucle infinie while invoquant de manière répétée os.system

Merci d'avoir vu mon message.

Tout d'abord, voici mon code :

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)
"""

Mon problème est que Ctrl + C ne fonctionne pas !

J'ai essayé de changer la position de try et faire fonctionner la capture des signaux (SIGINT).

Mais cela ne fonctionne pas non plus.

J'ai vu https://stackoverflow.com/a/8335212/5247212 , https://stackoverflow.com/a/32923070/5247212 et d'autres réponses concernant ce problème.

J'utilise MAC OS (10.12.3) et python 3.5.2.

5voto

farsil Points 510

C'est un comportement attendu, car os.system() est une enveloppe fine autour de la fonction C system() . Comme indiqué dans le page de manuel le processus parent ignore SIGINT pendant l'exécution de la commande. Afin de sortir de la boucle, vous devez vérifier manuellement le code de sortie du processus enfant (ceci est également mentionné dans la page de manuel) :

import os
import signal

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

Cependant, la méthode préférée (et plus pythique) pour obtenir le même résultat est d'utiliser la fonction subprocess module :

import subprocess

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

Votre code ressemblerait alors à quelque chose comme ceci :

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)

En complément, subprocess.run() n'est disponible que dans Python 3.5+. Vous pouvez utiliser subprocess.call() pour obtenir le même effet dans les anciennes versions de Python.

0voto

Rishabh Soni Points 104

Attrapez aussi "SystemExit"

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

0voto

Schmuddi Points 981

Le problème semble être que Ctrl+C est capturé par le sous-processus que vous appelez via os.system . Ce sous-processus réagit en conséquence, probablement en terminant ce qu'il est en train de faire. Si c'est le cas, la valeur de retour de os.system() sera différent de zéro. Vous pouvez utiliser cela pour casser le while boucle.

Voici un exemple qui fonctionne avec moi (en remplaçant say por sleep ):

import os
import sys

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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X