Entrada cronometrada Python

Oct 14 2020

Estou escrevendo um bot de jogo python em que um usuário precisa enviar uma entrada dentro de um determinado período de tempo.

Minha implementação atual disso é gerar um novo encadeamento que dorme por esse período de tempo e, em seguida, verificar se uma entrada foi enviada. Um nonce é adicionado porque o tempo pode acabar após o início de outro encadeamento, o que faria com que a if chatid in user_threadsparte fosse avaliada como verdadeira. Devo usar este método ou há uma solução melhor para ter uma entrada cronometrada (no sentido de menos probabilidade de falhar devido a condições de corrida semelhantes).

Também tentei usar, multiprocessing.Processmas compartilhar variáveis ​​com o outro processo parece ser muito mais complicado.

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

Respostas

2 Reinderien Oct 14 2020 at 00:41

O que @vnp disse. Fundamentalmente,

  • inputusa stdin;
  • stdin pode ser interpretado como um identificador de arquivo, desde que você não esteja no Windows;
  • select pode esperar pela disponibilidade de dados em tais identificadores.

Há muita ajuda da Internet neste tópico, incluindo https://stackoverflow.com/a/3471853/313768; para citar a solução 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..."