Input temporizzato Python

Oct 14 2020

Sto scrivendo un game-bot Python in cui un utente deve inviare un input entro un certo periodo di tempo.

La mia attuale implementazione di questo è generare un nuovo thread che dorme per quel periodo di tempo, quindi controlla se è stato inviato un input. Viene aggiunto un nonce poiché il tempo potrebbe scadere dopo l'avvio di un altro thread, il che farebbe sì che la if chatid in user_threadsparte restituisse true. Dovrei usare questo metodo o c'è una soluzione migliore per avere un input a tempo (nel senso che è meno probabile che fallisca a causa di condizioni di gara simili).

Ho anche provato a utilizzare, multiprocessing.Processma la condivisione delle variabili nell'altro processo sembra essere molto più ingombrante.

from threading import Thread
from time import time, sleep
from random import randint

user_threads = {}

def timeout(t,r):
    while time()-t<5:
        sleep(5-time()+t)
    if chatid in user_threads:
        if user_threads[chatid][3] != r:
            return
        del user_threads[chatid]
        print("Too slow")

def recvans(ans,inp):
    if ans==inp:
        print("yes")
    else:
        print("no")

def starttimer(chatid):
    r = randint(0,1<<128)
    user_threads[chatid] = [None,None,None,r]
    user_threads[chatid][2] = ["a"]
    P = Thread(target = timeout, args = (time(),r))
    user_threads[chatid][0] = P
    user_threads[chatid][1] = recvans
    P.start()

while True: # simulating user input from different users (here chatid=1)
    inp = input()
    chatid = 1
    if chatid in user_threads:
        t, func, args, _ = user_threads[chatid]
        if t == None:
            print("Please wait")
            continue
        del user_threads[chatid]
        args += [inp]
        func(*args)
        continue
    if inp == "Start":
        starttimer(chatid)
        continue
    if inp == "Quit":
        break
    print("Unknown msg")

Risposte

2 Reinderien Oct 14 2020 at 00:41

Cosa ha detto @vnp. Fondamentalmente,

  • inputusi stdin;
  • stdin può essere interpretato come un handle di file fintanto che non sei in Windows;
  • select può attendere la disponibilità dei dati su tali handle.

C'è molto aiuto su Internet su questo argomento, incluso https://stackoverflow.com/a/3471853/313768; per citare la soluzione lì:

import sys 
from select import select

timeout = 10 
print "Enter something:", 
rlist, _, _ = select([sys.stdin], [], [], timeout) 
if rlist:
    s = sys.stdin.readline()
    print s 
else:
    print "No input. Moving on..."