(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"