Python 如何在永久循环中停止等待从套接字接收的greenlet

Python 如何在永久循环中停止等待从套接字接收的greenlet,python,gevent,greenlets,Python,Gevent,Greenlets,我正在Python应用程序中编写一个简单的模块来与服务器通信。我使用gevent和zeromq套接字。此模块将在线程中运行 这是一个演示 import threading import gevent import zmq.green as zmq class SocketTest(threading.Thread): def __init__(self): threading.Thread.__init__(self) self.context = z

我正在Python应用程序中编写一个简单的模块来与服务器通信。我使用gevent和zeromq套接字。此模块将在线程中运行

这是一个演示

import threading
import gevent
import zmq.green as zmq


class SocketTest(threading.Thread):
    def __init__(self):
        threading.Thread.__init__(self)
        self.context = zmq.Context()
        self.socket = None
        self.running = False
        self.sock_greenlet = None

    def run(self):
        self.socket = self.context.socket(zmq.DEALER)
        self.socket.setsockopt(zmq.RCVTIMEO, 1000)
        self.socket.connect('tcp://127.0.0.1:9999')

        self.running = True
        self.sock_greenlet = gevent.spawn(self.process)
        print('Starting')
        self.sock_greenlet.join()

    def process(self):
        while self.running:
            print('Wait for data')
            data = self.socket.recv()
            # do something
            print(data)
            gevent.sleep(0.5)

    def stop(self):
        print('Stop app')
        self.running = False
        # I want to ask all greenlets to exit, or kill them
        # gevent.wait(timeout=0)
        gevent.kill(self.sock_greenlet)
        print('End of stop')


def test():
    try:
        app = SocketTest()
        app.start()
        app.join()
    except KeyboardInterrupt:
        app.stop()
        print('Exit')


if __name__ == '__main__':
    test()

当我按Ctrl+C时,我的应用程序不会退出。我知道我的线程正在运行一个事件循环。但我不知道如何正确地阻止greenlet
进程,或者杀死它

在主线程中,我将调用
app.stop
,如果我访问gevent循环的一些变量是否安全?
(当我的应用程序退出时,我想向服务器发送一条
再见消息)

我在所有项目中都使用它,效果很好

if __name__ == '__main__':
    server = WSGIServer(("0.0.0.0", int(port)), app , handler_class=WebSocketHandler)
    def shutdown():
        print('Shutting down ...')
        server.stop(timeout=60)
        exit(signal.SIGTERM)
    gevent.signal(signal.SIGTERM, shutdown)
    gevent.signal(signal.SIGINT, shutdown) #CTRL C
    server.serve_forever()

当greenlet
进程中的
self.running=False
时,我的线程可能会重复,但它会被阻止在
self.socket.recv()
我必须使用zeromq socket,因为我的服务器也使用zeromq。我们构建了一个定制的基于通信通道的tcp套接字,zeromq.gevent和zeromq可以很好地协同工作。我也在使用zmq.green。现在,我的解决方案是使用带超时的轮询器。
将gevent.timeout(2,False)作为超时
可以允许您在接收端进行轮询,但在间隔后继续并再次循环。它将对消息进行排队,直到能够处理它为止。我用它来制作WebSocket。