Benutzereingabe mit einem Timeout in einer Schleife

9

Ich versuche eine Looping-Python-Funktion zu erstellen, die eine Aufgabe ausführt und den Benutzer zur Eingabe einer Antwort auffordert. Wenn der Benutzer nicht innerhalb der angegebenen Zeit antwortet, wird die Sequenz wiederholt.

Dies basiert lose auf dieser Frage: Wie man das Zeitlimit für raw_input einstellt

Die Aufgabe wird durch some_function() repräsentiert. Das Timeout ist eine Variable in Sekunden. Ich habe zwei Probleme mit dem folgenden Code:

  1. Die raw_input-Eingabeaufforderung läuft nicht nach der angegebenen Zeit von 4 Sekunden ab, unabhängig davon, ob der Benutzer dazu aufgefordert wird oder nicht.

  2. Wenn raw_input von 'q' eingegeben wird (ohne '' weil ich weiß, dass irgendetwas eingegeben wird, wird es automatisch als String eingegeben), verlässt die Funktion die Schleife nicht.

'

%Vor%

'

    
user3374113 24.08.2015, 23:43
quelle

6 Antworten

3

Achtung: Dies soll in * nix und OSX wie gewünscht funktionieren, funktioniert aber unter Windows definitiv nicht.

Ich habe diese Änderung eines ActiveState-Rezepts als Grundlage für den folgenden Code verwendet. Es ist ein einfach zu bedienendes Objekt, das Eingaben mit einem Timeout lesen kann. Es verwendet Polling, um Zeichen nacheinander zu sammeln und das Verhalten von raw_input() / input() zu emulieren.

Eingabe mit Timeout

Hinweis: Offensichtlich funktioniert die folgende Methode _getch_nix() nicht für OP, aber für OSX 10.9.5. Möglicherweise haben Sie Glück, _getch_osx() aufzurufen, obwohl es nur in 32-Bit-Python zu funktionieren scheint, da Carbon 64-Bit nicht vollständig unterstützt.

%Vor%

Teste es

%Vor%

Wiederholter Eingang

Dies implementiert Ihre ursprüngliche Absicht, wie ich es verstehe. Ich sehe keinen Wert für rekursive Aufrufe - ich denke, was Sie wollen, ist nur wiederholt Eingabe zu erhalten? Bitte korrigieren Sie mich, wenn das falsch ist.

%Vor%     
KobeJohn 31.08.2015 14:43
quelle
1

Sie können vor der Eingabe einen Alarm festlegen und den Alarm dann an einen benutzerdefinierten Handler binden. Nach Ablauf des angegebenen Zeitraums werden Alarme ausgelöst. Handler löst eine Ausnahme aus, und die benutzerdefinierte input -Funktion kann den Rest verarbeiten.
ein kurzes Beispiel:

%Vor%

Kredit, wo es fällig ist: Tastatureingabe mit Timeout in Python

    
Kamyar Ghasemlou 03.09.2015 23:11
quelle
0

Ich glaube nicht, dass es eine Möglichkeit gibt, eine Eingabeaufforderung anzuzeigen, die nach Ablauf der Zeit abläuft, ohne dass eine andere Nachricht von einem anderen Thread angezeigt wird.

Sie können die folgende Zeile vor dem Aufruf von raw_input hinzufügen:

%Vor%

Sie können die Funktion interrupt_user wie folgt definieren:

%Vor%

Rufen Sie in der Funktion raw_input_with_time keinen Schlaf auf. Speichern Sie stattdessen die Zeit vor dem Aufruf von raw_input und bestimmen Sie, ob die verstrichene Zeit nach dem Aufruf mehr als 5 Sekunden beträgt. Wenn der Benutzer 'q' eingegeben hat, sollte er sich nicht selbst aufrufen, damit die Schleife stoppt.

    
Arthur Laks 24.08.2015 23:47
quelle
0

Eine andere Möglichkeit ist es, die IO-Blockierung in den neuen Thread einzufügen (im Gegensatz zu Ihrem vorgeschlagenen Schema, wo Sie es in Ihrem Haupt-Thread haben). Der Vorbehalt dafür ist, dass es keinen sauberen Weg gibt, einen Thread in Python zu löschen, also ist das nicht nett mit wiederholenden Aufrufen (N Threads werden bis zum Hauptende herumhängen, und ich denke, dass raw_input nicht nett spielt ...) .

Seien Sie also gewarnt, das funktioniert einmal, weit entfernt von der perfekten Lösung

%Vor%     
agomcas 03.09.2015 05:59
quelle
0

Das ist nur ein Konzept. Benutzer nach Eingabedaten fragen.

%Vor%     
Abc Xyz 03.09.2015 22:01
quelle
0

Was ist, wenn Sie anstelle von some_function , wenn die Eingabe abgelaufen ist, das in einen Hintergrund-Thread umwandeln, der mit einem Intervall des Timeouts weiterläuft? Die Arbeit wird fortgesetzt, während der Haupt-Thread permanent blockiert wird, während auf die Eingabe gewartet wird. Sie können sich entscheiden, anders auf diese Eingabe zu reagieren, basierend auf dem, was der Mitarbeiter tut (arbeiten oder schlafen) - Sie könnten ihn einfach komplett ignorieren. AFAIK, gibt es keinen erkennbaren Unterschied zwischen der Eingabe oder der Eingabe, aber dem Ignorieren. Diese Idee nutzt das.

Hinweis: Alles, was ich beabsichtige, ist, eine andere Art des Nachdenkens über das Problem zu zeigen, das in Ihrem speziellen Fall angemessen ist oder nicht. Ich denke aber, dass es sehr flexibel ist.

Beweis des Konzepts:

%Vor%

Es ist nicht auf etwas Plattformspezifisches angewiesen; Es ist nur einfacher Python-Code. Erst nachdem ich einige alternative Implementierungen aus einem Thread heraus getestet hatte, erkannte ich, wie viel von einem Vorteil, der Benutzereingaben für den Hauptthread übrig lässt, ist.

Ich habe nicht zu viel Wert darauf gelegt, dass es sicher und sauber ist, aber sicher kann es unter Beibehaltung der Gesamtstruktur gemacht werden. Der größte Fehler, den ich darin sehen kann, ist, dass frühere Eingaben niemals weggehen. Es verursacht Verwirrung, wenn der Worker ausgibt und die frühere Eingabe verdeckt. Wenn Sie q , aber nicht Enter rechtzeitig drücken, führt das Drücken von q und Enter beim nächsten Mal zur Eingabe von qq , auch wenn diese q s nicht nebeneinander auf dem Bildschirm angezeigt werden. Im Allgemeinen funktionieren Kommandozeilen-Anwendungen so, und ich bin mir nicht sicher, ob es sich lohnt, sie zu reparieren. Sie könnten auch eine Eingabe akzeptieren, die nur aus q s als Stornierung besteht. Eine andere Möglichkeit wäre, direkt von stdin zu lesen und nicht raw_input .

Eine Idee, um die Struktur des Code-Niceers zu machen, wäre, den Haupt-Thread dümmer zu machen und ihn dem Worker übergeben zu lassen (mit einer Queue), um zu entscheiden, was er tun soll.

    
Thijs van Dien 04.09.2015 00:26
quelle