简体   繁体   English

在 Cython 中使用 ZMQ

[英]Using ZMQ within Cython

I've gotten ZMQ to work in.py files but I want to use it in a cython class but have not figure out how to import the right library in to.pyx files.我已经让 ZMQ 在 .py 文件中工作,但我想在 cython 类中使用它,但还没有弄清楚如何在 to.pyx 文件中导入正确的库。 Example:例子:

import zmq
from zmq.backend.cython.socket cimport Socket
from zmq.backend.cython.context import Context

cdef class MyClass:

    cdef public str tick_port
    cdef public Socket socket
    cdef public Context context

    def __cinit__(self,tick_port):

        self.tick_port = tick_port

        self.context = zmq.Context()
        self.socket = self.context.socket(zmq.SUB)
        self.socket.setsockopt(zmq.SUBSCRIBE, b"")  # Note.

    
    def StartData(self):
        ''' market data comes in here '''
        self.socket.connect("tcp://127.0.0.1:" + str(self.tick_port))
        while True:
            tick_message = self.socket.recv_json()
            print("Data: " + str(tick_message))
            #self.OnTick(eval(tick_message))

how do you correctly declare and define various zmq variables within cython?您如何在 cython 中正确声明和定义各种 zmq 变量? so I still create context and socket objects like in python?所以我仍然像在 python 中一样创建contextsocket对象? Lots of newbie question but I couldn't find anything from googling "how to use zmq in cython".很多新手问题,但我无法通过谷歌搜索“如何在 cython 中使用 zmq”找到任何内容。

for example when compiling the above I get error:例如,在编译上述内容时出现错误:

C attribute of type '<error>' cannot be accessed from pythong.

Thanks,谢谢,

Things to note:注意事项:

  1. As mentioned in comments by user DavidW, it appears the Cython code utilizes Python objects & therefore using the Cython module directly from Cython doesn't benefit from possible speedups & releasing the GIL, etc. So just using cdef object context = zmq.Context() and cdef object socket = context.Socket(...) (etc.) is a fine way to go.正如用户 DavidW 在评论中提到的那样,Cython 代码似乎利用了 Python 对象,因此直接从 Cython 中使用 Cython 模块并没有从可能的加速和释放 GIL 等中受益。所以只使用cdef object context = zmq.Context()cdef object socket = context.Socket(...) (等)是一个很好的方法。 If you wanted to speed things up or achieve total releasing of the Python GIL within a function, you might need to wrap/call the CZMQ or libzmq libraries from your own Cython code.如果您想加快速度或在一个函数内实现 Python GIL 的完全释放,您可能需要从您自己的 Cython 代码中包装/调用 CZMQ 或 libzmq 库。
  2. You can still do what you were trying to do above & use the Cython types from Cython code.您仍然可以执行上面尝试执行的操作并使用 Cython 代码中的 Cython 类型。 However:然而:
    • As mentioned by user ead in comments, you have to cimport Context similar to how you cimport -ed Socket正如用户 ead 在评论中提到的那样,您必须cimport Context类似于cimport -ed Socket
    • The Socket and Context types within zmq.backend.cython have different interfaces from the high-level zmq.Socket and zmq.Context classes. zmq.backend.cython中的 Socket 和 Context 类型与高级zmq.Socketzmq.Context类具有不同的接口。 You will have to look at the code in the corresponding.pyx files for full details, but for the example above:您必须查看相应的 .pyx 文件中的代码以获取完整详细信息,但对于上面的示例:
      • The Cython Context class has no socket method. Cython Context类没有socket方法。 You have to instantiate a Socket manually, and the first argument is context=... , which you will use to specify the Context you instantiated prior.您必须手动实例化一个Socket ,第一个参数是context=... ,您将使用它来指定您之前实例化的Context
      • The Cython Socket class has no setsockopt method, but does have an equivalent set method. Cython Socket类没有setsockopt方法,但有一个等效的set方法。
      • The Cython Socket class has no recv_json method, so you will have to use recv and then convert the returned value to JSON using another library. Cython Socket类没有recv_json方法,因此您必须使用recv ,然后使用另一个库将返回值转换为 JSON。

See files context.pyx and socket.pyx in the codebase here: https://github.com/zeromq/pyzmq/tree/main/zmq/backend/cython在此处的代码库中查看文件context.pyxsocket.pyxhttps ://github.com/zeromq/pyzmq/tree/main/zmq/backend/cython

A corrected version of your code follows:您的代码的更正版本如下:

import zmq
from zmq.backend.cython.socket cimport Socket
from zmq.backend.cython.context cimport Context

cdef class MyClass:

    cdef public str tick_port
    cdef public Socket socket
    cdef public Context context

    def __cinit__(self,tick_port):

        self.tick_port = tick_port

        self.context = Context()
        self.socket = Socket(self.context, zmq.SUB)
        self.socket.set(zmq.SUBSCRIBE, b"")  # Note.

    
    def StartData(self):
        ''' market data comes in here '''
        self.socket.connect("tcp://127.0.0.1:" + str(self.tick_port))
        while True:
            tick_message = self.socket.recv()
            print("Data: " + str(tick_message))
            #self.OnTick(eval(tick_message))

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM