Python, выполняющий MessageQueue.Peek через win32com, как правильно установить время ожидания? - PullRequest
9 голосов
/ 01 ноября 2019

Для начала, я хотел бы сказать, что если кто-то может помочь здесь, вы невероятны.

Общий вопрос

Моя программа на Python должна взаимодействовать с MSMQ. По сути, я хочу посмотреть в очередь, указав тайм-аут, если в ней ничего нет.

Однако, несмотря на все мои усилия, я не могу заставить Peek () переждать интервал ожидания, когда нет значенияранее в очереди. Не могли бы вы указать, что отсутствует в этом коде?


Мой текущий код

Вот мой код прямо сейчас:

from socket import gethostname

import win32com.client
import pythoncom

import clr
clr.AddReference("System")
clr.AddReference("System.Messaging")
from System import TimeSpan
from System.Messaging import MessageQueue


# Source: [1]
# [1] https://docs.microsoft.com/en-us/previous-versions/windows/desktop/msmq/ms707027%28v%3dvs.85%29
MQ_DENY_NONE = 0x0
MQ_PEEK_ACCESS = 0x1
MQ_SEND_ACCESS = 0x2


# Set up queue
pythoncom.CoInitialize()
qinfo = win32com.client.Dispatch("MSMQ.MSMQQueueInfo")
qinfo.FormatName = f"direct=os:{gethostname()}\\PRIVATE$\\MyQueue"
queue = qinfo.Open(MQ_PEEK_ACCESS, MQ_DENY_NONE)

# Receive a value
timeout_sec = 1.0
timespan = TimeSpan.FromSeconds(timeout_sec)
label, body = "", ""
# TODO: timeout value does not appear working. It never waits when
#  there's no message
if queue.Peek(pythoncom.Empty, pythoncom.Empty, timespan):
    msg = queue.Receive() . # Blocking receive --> remove msg from the queue
    if msg is not None:
        label = msg.Label
        body = msg.Body

Я бегу: inspect.getfullargspec(queue.Peek) и получаю:

FullArgSpec(args=['self', 'WantDestinationQueue', 'WantBody', 'ReceiveTimeout', 'WantConnectorType'], varargs=None, varkw=None, defaults=(<PyOleMissing object at 0x00000147F5D43BD0>, <PyOleMissing object at 0x00000147F5D43BD0>, <PyOleMissing object at 0x00000147F5D43BD0>, <PyOleMissing object at 0x00000147F5D43BD0>), kwonlyargs=[], kwonlydefaults=None, annotations={})

Вещи, которые я пробовал

Этовопрос : высказывание ReceiveTimeout=timespan, похоже, не решает мою проблему.

Замена pythoncom.Empty на pythoncom.Missing, похоже, не работает

Этот вопрос без ответа кажется очень похожим на мой

Ответы [ 2 ]

0 голосов
/ 12 ноября 2019

В комментариях к исходному вопросу @PeterBrittain предложил попробовать просто использовать:

целое число (в миллисекундах) для их таймаута

Я попытался этои на самом деле, это сработало! Я нашел float значения для работы, а также. Вот пример кода Python:

timeout_sec = 1.0
queue.Peek(pythoncom.Empty, pythoncom.Empty, timeout_sec * 1000):

Спасибо @PeterBrittain!

0 голосов
/ 10 ноября 2019

Я нашел эту статью send-msmq-messages-python

В статье показано, как отправлять и получать сообщения с помощью msmq. Я не понимаю, почему вы не можете просто использовать стандартный синтаксис сокетного соединения, чтобы сказать, что если я не получил пакет / соединение, то закройте соединение

import select
mysocket.setblocking(0)
ready = select.select([mysocket], [], [], timeout_in_seconds)
if ready[0]:
    data = mysocket.recv(4096)

Так что подобное не должно быть слишком сложным. В худшем случае создайте поток, который каждый раз проверяет timeout_time, равна ли переменная нулю или нет. Если он равен нулю, очередь закрывается, ничего не принимается, если он> 0, установлен на ноль и ждет новых сообщений. Я также нашел GitHub об асинхронном msmq для регистрации в python. асинхронный msmq Этот только что сказал, получает, в то время как True dlopes7 msmq

import time
t_end = time.time() + 60 * 15
messages=0
while time.time() < t_end or messages>0:
    msg = queue.Receive()
    messages+=1
    if(time.time() > t_end and messages>0):
        messages=0
        t_end = time.time() + 60 * 15
    print(f'Got Message from {queue_name}: {msg.Label} - {msg.Body}')

Не тот ответ, который вы хотели, но тот, который будет работать.

...