So beenden Sie eine unendliche Schleife sicher in Python?
Ich habe ein Skript, das läuft auf einer Endlosschleife, und fügt die Dinge in eine Datenbank und nicht Dinge, die ich kann nicht aufhören auf halbem Weg durch, also kann ich nicht einfach Strg+C drücken und es zu stoppen.
Ich möchte in der Lage sein, um irgendwie zu stoppen eine while-Schleife, aber lassen Sie es zu beenden, es ist letzten iteration, bevor es Stoppt.
Lassen Sie mich klarstellen:
mein code sieht ungefähr so aus:
while True:
does something
does more things
does more things
Ich möchte in der Lage sein, zu unterbrechen, die while-Schleife am Ende, oder am Anfang, aber nicht zwischen die Dinge zu tun, weil das wäre schlecht.
und ich will nicht, es zu Fragen, mich nach jeder iteration, ob ich den Vorgang fortsetzen möchten.
danke für die tollen Antworten, ich bin super dankbar aber meine Implementierung scheint nicht zu funktionieren:
def signal_handler(signal, frame):
global interrupted
interrupted = True
class Crawler():
def __init__(self):
# not relevent
def crawl(self):
interrupted = False
signal.signal(signal.SIGINT, signal_handler)
while True:
doing things
more things
if interrupted:
print("Exiting..")
break
wenn ich drücken Sie Strg+c das Programm einfach immer weiter, ignoriert mich
- Sie haben keine Möglichkeit zu bestimmen, in deinem Skript, wenn der Auftrag abgeschlossen ist (letzten)! Wenn Sie tun, dann verwenden Sie es in einem Zustand und verwenden eine break-Anweisung
- Der job in diesem Fall ist ein web-crawler kann, als weiterzumachen auf unbestimmte Zeit. Ich möchte in der Lage sein zu sagen, es zu stoppen, kriecht aber nicht nur unterbrechen, es in der Mitte einer Seite zum Beispiel.
- lassen Sie es zu beenden, es ist letzten iteration, bevor es Stoppt? Wie wissen Sie, wenn es getan hat, den job oder nicht?
- das script crawlt Webseiten. es hat eine for-Schleife im inneren eine unendliche while-Schleife. Ich möchte in der Lage zu stoppen die unendliche while-Schleife, aber nicht während einer iteration der for-Schleife im inneren.
- Hmm...könntest du der wichtige Teil des Skripts? Dies kann anderen helfen, zu verstehen, was Sie wollen 😛
- Die Frage ist klar: Beenden Sie diese iteration der Schleife, die dann beendet wird. Und wer denkt, dass es off-topic?
Du musst angemeldet sein, um einen Kommentar abzugeben.
Was Sie tun müssen, ist zu fangen den interrupt ein flag setzen, sagen, dass Sie unterbrochen wurden, aber dann arbeiten Sie weiter, bis es ist Zeit, um die Flagge (am Ende jeder Schleife). Da python try-except-Konstrukt verlassen wird der aktuelle Durchlauf der Schleife, die Sie benötigen, um ein geeignetes signal-handler; es werde behandeln Sie die Unterbrechung, aber dann lass python weiter, wo es aufgehört hat. Hier ist, wie:
Hinweise:
Verwenden Sie diese von der Kommandozeile aus. In der IDLE-Konsole, es werde trampeln auf IDLE eigenen interrupt-handling.
Eine bessere Lösung wäre, um "block" KeyboardInterrupt für die Dauer der Schleife, und entsperren Sie Sie, wenn es Zeit, um Abfragen für interrupts. Dies ist ein feature von einigen Unix-Varianten, aber nicht alle, daher python nicht unterstützt (siehe die Dritte "Regel")
Den OP will, um dies zu tun, die in einer Klasse. Aber die interrupt-Funktion aufgerufen wird, indem Sie die signal-handling-system, mit zwei Argumenten: mit Der signal-Nummer und ein pointer zum stack-frame-- kein Platz für ein
self
argument, die Zugang zu der Klasse object. Daher ist der einfachste Weg, ein flag zu setzen ist eine Globale variable verwenden. Sie können rig einen Zeiger auf den lokalen Kontext durch die Verwendung von closures (D. H., definieren Sie die signal-handler dynamisch in__init__()
, aber ehrlich gesagt, ich würde nicht stören, es sei denn eine Globale Frage wegen multi-threading oder was auch immer.Einschränkung: Wenn Ihr Prozess ist in der Mitte von einem system-call, handling ein signal interrupt system call. So dies möglicherweise nicht sicher für alle Anwendungen. Sicherere alternativen wäre (ein), Anstatt sich auf Signale, verwenden Sie eine nicht-blockierende lese-am Ende jeder loop-iteration (und geben Sie input drücken Sie anstelle des Schlagens ^C); (b) Benutzung von threads oder der Kommunikation zwischen Prozessen zu isolieren, die Arbeiter aus dem signal-handling; oder (c) die Arbeit der Umsetzung real signal-blockieren, wenn Sie auf einem OS, die es hat. Alle von Ihnen sind OS-abhängig zum Teil, also werde ich es dabei belassen.
crawl()
setzen, und dann prüfen, eine local variableinterrupted
🙂 Es muss global sein, so wird der interrupt-handler kann um es zu bekommen.die unter Logik wird Ihnen dabei helfen,
während Sie dies ausführen, drücken Sie STRG+C
Ich hoffe, dass Sie folgenden code würde helfen:
Klären @praba230890 die Lösung: Die
interrupted
variable wurde nicht definiert, in den richtigen Bereich. Es wurde definiert, in dercrawl
Funktion und der hf nicht erreichen konnte, die es als Globale variable, die nach der definition der Prozedur auf die Wurzel des Programms.