Wejście czasowe w Pythonie

Oct 14 2020

Piszę bota do gry w Pythonie, w którym użytkownik musi wysłać dane wejściowe w określonym czasie.

Moja obecna implementacja polega na utworzeniu nowego wątku, który śpi przez ten czas, a następnie sprawdza, czy dane wejściowe zostały wysłane. Dodawana jest wartość jednorazowa, ponieważ czas może upłynąć po uruchomieniu innego wątku, co spowodowałoby, że if chatid in user_threadsczęść została oszacowana jako prawda. Czy powinienem użyć tej metody, czy jest lepsze rozwiązanie, jeśli chodzi o czasowe wejście (w sensie mniej prawdopodobne, że zawiedzie z powodu podobnych warunków wyścigu).

Próbowałem też używać, multiprocessing.Processale udostępnianie zmiennych innemu procesowi wydaje się znacznie bardziej kłopotliwe.

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

Odpowiedzi

2 Reinderien Oct 14 2020 at 00:41

Co powiedział @vnp. Zasadniczo,

  • inputzastosowania stdin;
  • stdin może być interpretowane jako uchwyt pliku, o ile nie jesteś w systemie Windows;
  • select mogą czekać na dostępność danych na takich uchwytach.

Istnieje wiele pomocy internetowych na ten temat, w tym https://stackoverflow.com/a/3471853/313768; przytoczyć tam rozwiązanie:

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