问题
I am trying to run a program that takes in input as a job is getting done. I have looked through several forms, and looked into the documentation. I'm running this in Debian, and I understand that I can use this getch function to receive characters without hitting the return key. To break it down, this is what I am trying to implement in my infinite while loop
- Take in input (threading didn't work here for me
- Put input into Queue
- If there are no running jobs, start the job with the item in front of the queue as a variable
I am also running the threading module to execute another instruction. Is there any way I can do this?
Update: This is what I have tried so far:
First, I tried using a timer from the threading module to stop it from waiting, which went something like this.
def getchnow():
def time_up():
answer= None
print 'time up...'
wait = Timer(5,time_up) # x is amount of time in seconds
wait.start()
try:
print "enter answer below"
answer = getch()
except Exception:
print 'pass\n'
answer = None
if answer != True: # it means if variable have somthing
wait.cancel() # time_up will not execute(so, no skip)
return answer
line = getchnow()
#Add line variable to queue
#Do stuff with queue
The problem here is that it still waited for user input.
I then tried to put the getch function into another thread.
q = Queue.Queue
q.put(getch())
if q.get() != True: # it means if variable have somthing
line = q.get()
#Add line variable to queue
#Do stuff with queue
This attempt doesn't let me do anything.
回答1:
I read more of this link, and there was an implementation of what I wanted at the bottom.
I used the select module for a Non-Blocking implementation on Linux. This times out in (5 seconds here) if no input is received. Particularly useful when used in a thread, so that the getch call is non-blocking and will allow the thread to exit cleanly
# This class gets a single character input from the keyboard
class _GetchUnix:
def __init__(self):
import tty, sys
from select import select
def __call__(self):
import sys, tty, termios
from select import select
fd = sys.stdin.fileno()
old_settings = termios.tcgetattr(fd)
try:
tty.setraw(sys.stdin.fileno())
[i, o, e] = select([sys.stdin.fileno()], [], [], 2)
if i:
ch=sys.stdin.read(1)
else:
ch=''
finally:
termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
return ch
getch = _GetchUnix()
# End Class
回答2:
I've also used [i, o, e] = select([sys.stdin.fileno()], [], [], 2)
, but I've heard it might not work on windows. If anyone still needs a multi-threaded, non-blocking input example:
import threading
import sys
import time
bufferLock=threading.Lock()
inputBuffer=[]
class InputThread(threading.Thread):
def run(self):
global inputBuffer
print("starting input")
while True:
line=sys.stdin.readline()
bufferLock.acquire()
inputBuffer.insert(0,line)
bufferLock.release()
input_thread=InputThread()
input_thread.start()
while True:
time.sleep(4)
bufferLock.acquire()
if len(inputBuffer)>0:
print("Popping: "+inputBuffer.pop())
bufferLock.release()
来源:https://stackoverflow.com/questions/15302883/python-in-linux-put-user-input-asynchronously-into-queue