Невозможно вернуться из функции, которая использует zmq в Python 3 django - PullRequest
0 голосов
/ 20 сентября 2018

Я использую Python 3.6.6 и 64-битные окна anaconda, zmq 4.2.5 У меня очень странное поведение: функция не может вернуться.

Сервер:

import zmq
import json

def main():
    context = zmq.Context()
    socket = context.socket(zmq.REP)
    #socket.setsockopt(zmq.RCVTIMEO, 1000)
    socket.setsockopt(zmq.SNDTIMEO, 1000)
    socket.bind(my_address)

    def send_response(**kwargs):
        try:
            #... Some kwargs standard preprocessing
            socket.send_string(json.dumps(kwargs))
        except zmq.ZMQBaseError:
            return False
        return True

    while True:
        try:
            msg = socket.recv().decode("utf-8")
        except zmq.ZMQBaseError:
            continue
        #... Processing
        if not send_response(error='Everything is wrong'):
            continue
        #... Processing

Клиент:

import zmq
import json

def do_request(**kwargs):
    context = zmq.Context()
    socket = context.socket(zmq.REQ)
    socket.setsockopt(zmq.RCVTIMEO, 5000)
    socket.setsockopt(zmq.SNDTIMEO, 1000)
    socket.connect(my_address)

    #... kwargs pre-rocessing
    try:
        socket.send_string(json.dumps(kwargs))
        response = json.loads(socket.recv().decode("utf-8"))
        #... Processing
        return response
    except zmq.ZMQBaseError as e:
        print(e)
        print("PING1!!!")
        return dict(error='Service temporarily unavailable', r_status=503)

def called_from_view():
    response = do_request(command='ping')
    print("PING2!!!")

Работало.Я не знаю, что изменилось.Но сейчас это сломано.Когда сервер выключен, клиент do_request не возвращает Service temporarily unavailable.response = json.loads(socket.recv().decode("utf-8")) вызывает исключение.В секции except python печатает PING1, но после этого не печатает PING2 в called_from_view.Даже с пустым возвращением.Я не могу понять, почему.

Я создаю новый сокет в do_request, потому что клиент called_from_view вызывается с точки зрения django.У меня раньше были другие проблемы с глобальным сокетом.

1 Ответ

0 голосов
/ 21 сентября 2018

Добавьте эту опцию после создания сокета в клиенте (вы также можете сохранить другие опции):

socket = context.socket(zmq.REQ)
socket.setsockopt(zmq.LINGER, True) # or False, my testing says it works both ways.

См. этот SO-ответ для справки.По сути, сборщик мусора пытается собрать кусочки при возврате из do_request, и сокет zmq мешает ему завершить работу, и он зависает бесконечно.

...