Python3 ZMQ, функция прерывания и вызов другого при каждом новом полученном сообщении - PullRequest
1 голос
/ 23 января 2020

Вот моя проблема: у меня есть 2 программы, общающиеся благодаря zmq через произвольный порт tcp. Когда # 1 получает сообщение от # 2, он должен вызвать какую-то функцию. Если # 1 получает сообщение до завершения текущей функции, я бы хотел # 1 прервать текущую функцию и вызвать новую. Я пытался использовать threading.Event, чтобы прервать функцию. Я не знаю, подходит ли zmq для моих нужд или подходит ли сокет.

Чтобы упростить, я покажу простейшую возможную версию, вот что я попробовал: p1.py

import zmq
from threading import Event

port_p2 = "6655"
context = zmq.Context()
socket = context.socket(zmq.PAIR)
socket.connect("tcp://localhost:%s" % port_p2)
print("port 6655")

__exit1 = Event()
__exit2 = Event()


def action1():
    __exit1.clear()
    __exit2.set()
    while not __exit1.is_set():
        for i in range(1, 20):
            print(i)
            time.sleep(1)
        __exit1.set()


def action2():
    __exit2.clear()
    __exit1.set()
    while not __exit2.is_set():
        for i in range(1, 20):
            print(i * 100)
            time.sleep(1)
        __exit2.set()


if __name__ == "__main__":
    try:
        while True:
            try:
                string = socket.recv(flags=zmq.NOBLOCK)
                # message received, process it
                string = str(string, 'utf-8')
                if "Action1" in string:
                    action1()
                if "Action2" in string:
                    action2()
            except zmq.Again as e:
                # No messages waiting to be processed
                pass
            time.sleep(0.1)
    except(KeyboardInterrupt, SystemExit):
        print("exit")

и p2.py

import time
import random

port_p1 = "6655"
context = zmq.Context()
socket_p1 = context.socket(zmq.PAIR)
socket_p1.bind("tcp://*:%s" % port_p1)
print("port 6655")


if __name__ == "__main__":

    while True:
        i = random.choice(range(1, 10))
        print(i)
        try:
            if random.choice([True, False]):
                print("Action 1")
                socket_p1.send(b'Action1')
            else:
                socket_p1.send(b'Action2')
                print("Action 2")
        except zmq.Again as e:
            pass
        time.sleep(i)

Для своих целей я не хотел / не могу использовать системные сигналы

Буду признателен за любой ввод и не стесняюсь просить точности, я должен признаться, что мне было трудно записать это. Спасибо

1 Ответ

0 голосов
/ 24 января 2020

Q : подобно # 1 для прерывания текущей функции…

Учитывая, что вы запретили используйте сигналы, # 1 может, но пассивно сигнализировать (будь то в рамках существующей инфраструктуры ZeroMQ или нет) функция , чтобы не продолжать дальше и вернуться в пре - зрелая мода (таким образом, fun() должен быть соответствующим образом изменен для выполнения этой активной повторной проверки, лучше всего в некоторой разумно гранулированной прогрессивной манере, регулярно проверяя активно # 1, если действительно пассивно сигнализировал («говорит» fun()) RET рано, из-за какой-либо причины и способа, который # 1 имел и использовал для этого).

Другой шанс состоит в том, чтобы расширить уже существующую инфраструктуру ZeroMQ (Context() -экземпляры) с артиллерией сокет-монитора и сделать fun() .connect() -прямо к ресурсам сокет-монитора, чтобы активно узнавать о любом новом сообщении, поступающем на # 1 (то есть автономно, без инициативы # 1) и решающем вернуться заранее. -зрелый f В тех случаях, когда это возможно, в соответствии с логикой вашего приложения c.

В случае сокета-монитора документация API содержит все детали, необходимые для реализации, которые в противном случае go выходили бы за рамки поста переполнения стека.

...