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 дякую, що насправді зробив трюк! Я розмістив ваш коментар як відповідь нижче.
Intrastellar Explorer

Відповіді:


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
Michael Hearn

0

У оригінальних коментарях запитання @PeterBrittain запропонував спробувати просто скористатися:

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

Я дістався, щоб спробувати це, і власне, це спрацювало! Я знайшов, що floatцінності також працюють. Ось приклад коду Python:

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

Дякую @PeterBrittain!

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.