0

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.

Community
  • 1
  • 1
user2125538
  • 147
  • 2
  • 4
  • 15
  • Yes, but perhaps if you provide an idea of what you've tried, we can help you get there. – Michael Mar 08 '13 at 20:49
  • @Michael Just updated – user2125538 Mar 08 '13 at 21:03
  • Putting aside the question why are you trying to run such things from a terminal at all, I'd suggest that you use `curses` for all your advanced terminal input and output needs. – 9000 Mar 08 '13 at 21:57
  • @9000 Can you tell me of a way to do this with the curses module? – user2125538 Mar 08 '13 at 22:17
  • @9000 I would like to run this program once I boot my system. Curses won't allow me to do that as well as if I run it through the terminal. – user2125538 Mar 08 '13 at 22:38
  • 1
    You need to use select() to poll without blocking, or you can use termios. You can use select() with stdin on Linux but that won't be portable to Windows. –  Mar 08 '13 at 22:45
  • @gecko I haven't thought of doing it that way. Is there a way to differentiate between getting an actual input to getting a null value? – user2125538 Mar 08 '13 at 23:26
  • @user2125538. The code here works. If you only put stdin in the read set, you will get an epmty list on no input, and anything else on input. It's exactly the same as tcp/ip socket code except it reads stdin not a TCP socket (becuase Linux treats stdin as a socket). Note the time out for select is set to 0.0 so it doesn't block. http://code.activestate.com/recipes/572182-how-to-implement-kbhit-on-linux/ –  Mar 09 '13 at 03:54

2 Answers2

0

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
user2125538
  • 147
  • 2
  • 4
  • 15
0

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()
Kenkron
  • 573
  • 1
  • 3
  • 15