Manipulate GIL to have Python thread work with pthread native ones
qshhnkf at alumni.sjtu.edu.cn
qshhnkf at alumni.sjtu.edu.cn
Tue May 31 01:16:22 EDT 2016
Hi Python experts,
I need to extend Python with C/C++ to interact with an in-house legacy API. I'm implementing a data subscriber with Python, which subscribes to a data publisher (actually a ZeroMQ publisher socket) and will get notified once any new messages are fed. In my subscriber, the messages are dumped to a data processor after received. The subscriber will also get notified by the processor when done. Since the data processor is written in C++, I have to extend the Python code with a simple C++ module.
Below is a simplified runnable code sample of my data subscriber. Code main.py , in which the module proc represents the processor, subscribe to a ZeroMQ socket on localhost:10000 , setup the callback, and send the received message to the processor by calling proc.onMsg .
#!/bin/python
# main.py
import gevent
import logging
import zmq.green as zmq
import pub
import proc
logging.basicConfig( format='[%(levelname)s] %(message)s', level=logging.DEBUG )
SUB_ADDR = 'tcp://localhost:10000'
def setupMqAndReceive():
'''Setup the message queue and receive messages.
'''
ctx = zmq.Context()
sock = ctx.socket( zmq.SUB )
# add topics
sock.setsockopt_string( zmq.SUBSCRIBE, 'Hello' )
sock.connect( SUB_ADDR )
while True:
msg = sock.recv().decode( 'utf-8' )
proc.onMsg( msg )
def callback( a, b ):
print( '[callback]', a, b )
def main():
'''Entrance of the module.
'''
pub.start()
proc.setCallback( callback )
'''A simple on-liner
gevent.spawn( setupMqAndReceive ).join()
works. However, the received messages will not be
processed by the processor.
'''
gevent.spawn( setupMqAndReceive )
proc.start()
Module proc is simplified with three functions exported:
* setCallback setup the callback function, so that when the message processed, my subscriber could be notified;
* onMsg is invoked by the subscriber;
* start setups a new worker thread to handle the messages from subscriber and make the main thread join to wait for the worker thread to exit.
The full version of source code could be found on github at https://github.com/more-more-tea/python_gil . Nevertheless, it does not run as my expectation. Once the processor thread is added, the subscriber cannot receive data from the publisher in the gevent loop. If I simply drop the data processor module, the subscriber gevent loop could receive the messages from the publisher. The same behavior could be observed with threading.Thread instead of gevent.
I posted the same question on StackOverflow
http://stackoverflow.com/questions/37513957/does-python-gil-need-to-be-taken-care-when-work-with-multi-thread-c-extension
with one answer direct me to the article
https://docs.python.org/3/c-api/init.html#thread-state-and-the-global-interpreter-lock
I read the document but still not sure where to add the
PyGILState_Ensure/PyGILState_Release. Without a running sample, it is a little bit hard to understand how Python thread and the native pthread interact.
Would you mind review the source code and direct the right way to make it running?
Thank you very much for your time and best regards!
Shuang
More information about the Python-list
mailing list