Как zmq.poll () какой-нибудь сокет и какая-то переменная? - PullRequest
0 голосов
/ 16 марта 2020

Я пытаюсь опросить несколько сокетов и multiprocessing.Event
Документация гласит:

A zmq.Socket или любой Python объект, имеющий метод fileno(), который возвращает действительный дескриптор файла .

, что означает, что я не могу использовать свой Event, но я должен иметь возможность использовать файл (как возвращено из open(...) или io объекта (что-нибудь из io) библиотека), но у меня ничего не получается:

Traceback (most recent call last):
  File "C:\Program Files\JetBrains\PyCharm Community Edition 2017.3\helpers\pydev\pydevd.py", line 1683, in <module>
    main()
  File "C:\Program Files\JetBrains\PyCharm Community Edition 2017.3\helpers\pydev\pydevd.py", line 1677, in main
    globals = debugger.run(setup['file'], None, None, is_module)
  File "C:\Program Files\JetBrains\PyCharm Community Edition 2017.3\helpers\pydev\pydevd.py", line 1087, in run
    pydev_imports.execfile(file, globals, locals)  # execute the script
  File "C:\Program Files\JetBrains\PyCharm Community Edition 2017.3\helpers\pydev\_pydev_imps\_pydev_execfile.py", line 18, in execfile
    exec(compile(contents+"\n", file, 'exec'), glob, loc)
  File "C:\work\polldamnyou.py", line 122, in <module>
    p = poller.poll(1000)
  File "C:\WinPython-64bit-3.6.3.0Qt5\python-3.6.3.amd64\Lib\site-packages\zmq\sugar\poll.py", line 99, in poll
    return zmq_poll(self.sockets, timeout=timeout)
  File "zmq\backend\cython\_poll.pyx", line 143, in zmq.backend.cython._poll.zmq_poll
  File "zmq\backend\cython\_poll.pyx", line 123, in zmq.backend.cython._poll.zmq_poll
  File "zmq\backend\cython\checkrc.pxd", line 25, in zmq.backend.cython.checkrc._check_rc
zmq.error.ZMQError: Unknown error

Я нашел тот же вопрос , который задавался ранее, но я решил использовать другой сокет, который обходил проблему. Любопытно и хочу увидеть, как это работает. Есть ли у кого-нибудь какие-либо подсказки, какой тип объекта можно использовать в zmq.Poller, кроме сокета?

Редактировать: несколько вещей, которые я пробовал

import traceback, os, zmq


def poll(poller):
    try:
        print('polled: ', poller.poll(3))
    except zmq.error.ZMQError as e:
        traceback.print_exc()


class Pollable:
    def __init__(self):
        self.fd = os.open('dump', os.O_RDWR | os.O_BINARY)
        self.FD = self.fd
        self.events = 0
        self.EVENTS = 0
        self.revents = 0
        self.REVENTS = 0

    def fileno(self):
        return self.fd

    def __getattribute__(self, item):
        if item != '__class__':
            print("requested: ", item)
        return super().__getattribute__(item)

ctx = zmq.Context()
sock = ctx.socket(zmq.SUB)
poller = zmq.Poller()
poller.register(sock, zmq.POLLIN)
poll(poller)  # works
file = open('dump', 'w+b')
print("fileno: ", file.fileno())
poller.register(file, zmq.POLLIN)
poll(poller)  # fails
file.events = 0
file.revents = 0
file.EVENTS = 0
file.REVENTS = 0
file.fd = file.fileno()
file.FD = file.fileno()
poll(poller)  # still fails
poller.unregister(file)
file.close()
poll(poller)  # works
fd = os.open('dump', os.O_RDWR|os.O_BINARY)
print("fd: ", fd)
dummy = Pollable()
poller.register(dummy, zmq.POLLIN)
poll(poller)  # fails

__getattribute__ показывает, что к fd и fileno обращаются, но больше ничего, так в чем же дело?!

1 Ответ

1 голос
/ 23 марта 2020

В случае, если кто-то никогда не работал с ZeroMQ,
здесь можно вначале насладиться "принципами ZeroMQ * менее чем за пять секунд"
, прежде чем углубляться в детали



Q : " какой вид объекта можно использовать в zmq.Poller, кроме розетки? "

Добро пожаловать в прекрасные земли дзен-ноль , И опубликованный API, и pyzmq ReadTheDocs понятны в этом отношении:

Функция zmq_poll() обеспечивает механизм для приложений для мультиплексирования ввода / вывода события на уровне уровня через набор розеток. Каждый член массива, на который указывает аргумент items, имеет структуру zmq_pollitem_t. Аргумент nitems указывает количество элементов в массиве элементов. Структура zmq_pollitem_t определяется следующим образом:

typedef struct
{
    void //*socket//;
    int //fd//;
    short //events//;
    short //revents//;
} zmq_pollitem_t;

Для каждого элемента zmq_pollitem_t zmq_poll() должен проверять либо сокет ØMQ, на который ссылается сокет или стандартный сокет, заданный дескриптором файла fd, для событий, указанных в событиях. Если и сокет, и fd установлены в одном zmq_pollitem_t, сокет ØMQ, на который ссылается сокет, имеет приоритет, и значение fd должно игнорироваться.

Для каждого элемента zmq_pollitem_t, zmq_poll() должен сначала очистить элемент revents, а затем указать любые запрошенные события, которые произошли, установив бит, соответствующий условию события в revents участник.

Если ни одно из запрошенных событий не произошло ни в одном элементе zmq_pollitem_t, zmq_poll() будет ожидать timeout миллисекунд, пока событие не произойдет ни в одном из запрошенных элементов. Если значение тайм-аута равно 0, zmq_poll() должен немедленно вернуться. Если значение timeout равно -1, zmq_poll() блокируется на неопределенный срок, пока запрошенное событие не произойдет хотя бы на одном zmq_pollitem_t.


Последнее, но не по крайней мере,
API явно предупрежден о реализации:

zmq_poll() функция может быть реализована или эмулируется с использованием интерфейсов операционной системы, отличных от poll(), и , как таковые, могут подчиняться ограничениям этих интерфейсов способами, не определенными в этой документации .


Решение:

Для любого желаемого объекта - poll(), который не соответствует заданному обязательное свойство наличия обычного fd -filedescriptor, реализовать такое обязательное свойство посреднический-прокси, отвечающее опубликованным API-спецификациям или не использовать его с zmq_poll() для успешных вызовов API.

Нет третий вариант.

...