Python, выполняющий MessageQueue.Peek через win32com, как правильно установить время ожидания?

9

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

Общий вопрос

Моя программа на 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не похоже на работу

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

Внутризвездный исследователь
источник
Pythoncom имеет CoWaitForMultipleHandles(Flags, Timeout , Handles )это помогает вам?
LinPy
Привет @LinPy ты не против разработки? Это может помочь, хотя вроде как обходной путь. Мне интересно, как получить аргументы правильно для тайм-аутаqueue.Peek
Intrastellar Explorer
1
Просто мысль, но другие примеры этого интерфейса в Python, которые я видел, просто используют целое число (в миллисекундах) для своего тайм-аута. Возможно, pywin32 не обрабатывает TimeSpans так, как вы ожидаете ...
Питер Бриттен
@PeterBrittain спасибо, что на самом деле сделали свое дело! Я разместил ваш комментарий как ответ ниже.
Внутризвездный исследователь

Ответы:

0

Я нашел эту статью посылку-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}')

Не тот ответ, который вы хотели, а тот, который сработает.

Майкл Хирн
источник
Здравствуйте @MichaelHearn! Спасибо за предоставление нескольких полезных обходных путей. Таким образом, я награждаю вас за вознаграждение :)
Intrastellar Explorer
Спасибо! @IntrastellarExplorer
Майкл Хирн
0

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

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

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

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

Спасибо @PeterBrittain!

Внутризвездный исследователь
источник