3
\$\begingroup\$

I'm writing a python game-bot where a user needs to send in an input within a certain amount of time.

My current implementation of this is to spawn a new thread that sleeps for that amount of time, then checks if an input has been sent. A nonce is added as the time could run out after another thread starts which would cause the if chatid in user_threads part to evaluate to true. Should I use this method or is there a better solution to having a timed input (in the sense less likely to fail due to like race conditions).

I've also tried using multiprocessing.Process but sharing variables to the other process seems to be a lot more cumbersome.

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")
\$\endgroup\$
  • 3
    \$\begingroup\$ Usually is is done via select.select \$\endgroup\$ – vnp Oct 13 at 15:29
2
\$\begingroup\$

What @vnp said. Fundamentally,

  • input uses stdin;
  • stdin can be interpreted as a file handle so long as you're not in Windows;
  • select can wait for data availability on such handles.

There's a lot of internet help on this topic, including https://stackoverflow.com/a/3471853/313768 ; to quote the solution there:

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..."
| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ ahh ic this looks way cleaner for my case since I'm using this in context of a game which receives http(s) requests is there a similar way to do this? \$\endgroup\$ – Ariana Oct 14 at 13:08

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.