2
\$\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")
Ben A
10.7k5 gold badges37 silver badges101 bronze badges
asked Oct 13, 2020 at 15:01
\$\endgroup\$
1
  • 3
    \$\begingroup\$ Usually is is done via select.select \$\endgroup\$ Commented Oct 13, 2020 at 15:29

1 Answer 1

1
\$\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..."
answered Oct 13, 2020 at 17:41
\$\endgroup\$
1
  • \$\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\$ Commented Oct 14, 2020 at 13:08

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.