Skip to content Skip to sidebar Skip to footer

(python) Using Threading To Look For Key Input With Getch

I've been trying to write a piece of test code which will continually print 'Running' until a key is pressed. I've tried to implement this by creating an additional thread (called

Solution 1:

You're hitting this issue because of the GIL. It works fine if you make the threading.Thread a multiprocessing.Process:

classmyThread (multiprocessing.Process):
    def__init__(self, threadID, name, cont):
        super(myThread, self).__init__()
        #threading.Thread.__init__(self)
        self.threadID = threadID
        self.name = name
        self.cont = contdefrun(self):
        print"Starting " + self.name +"\n"
        char = getch.getch()
        print'You pressed %s' % char
        cont.append(1)
        print"Terminating" + self.name

cont = []

thread1 = myThread(1, "Thread1", cont)

thread1.start()

while cont == []: 
    print"Running"
    time.sleep(0.5)

Output:

dan@dantop:~$ ./get.py 
Running
Starting Thread1

RunningRunningRunningRunningRunningRunningRunningRunning
You pressed f
TerminatingThread1
RunningRunningRunningRunningRunningRunningRunningRunning

getch is a C-extension, and is doing a blocking call to getchar(), but it doesn't release the GIL first. Because Python cannot actually run two threads concurrently, it gets stuck in the worker thread waiting for blocking call to getchar().

You can actually fix this bug pretty easily, by explicitly releasing the GIL from the getch C-extension code, using Py_BEGIN_THREADS and Py_ALLOW_THREADS:

static PyObject *getch_getche(PyObject *self, PyObject *args){
    int ok = PyArg_ParseTuple(args, "");
    char c;
    Py_BEGIN_ALLOW_THREADS
    c = getche();
    Py_END_ALLOW_THREADS
    returnPyUnicode_FromFormat("%c", c); 
}

static PyObject *getch_getch(PyObject *self, PyObject *args){
    int ok = PyArg_ParseTuple(args, "");
    char c;
    Py_BEGIN_ALLOW_THREADS
    c = getch();
    Py_END_ALLOW_THREADS
    returnPyUnicode_FromFormat("%c", c); 
}

If you make that change to getchmodule.c and rebuild the extension, the original, thread-using, example code works fine.

Post a Comment for "(python) Using Threading To Look For Key Input With Getch"