简体   繁体   中英

Python running MessageQueue.Peek via win32com, how to get timeout right?

For starters, I would like to say if anyone can help here, you are incredible.

General Question

My Python program needs to interact with MSMQ. Basically, I want to peek at a queue, specifying a timeout if there's nothing in the queue.

However, despite my best efforts, I cannot get Peek() to wait out the timeout interval, when there's no value previously in the queue. Can you please point out what is missing from this code?


My Current Code

Here is my code right now:

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

I run: inspect.getfullargspec(queue.Peek) and get:

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={})

Things I've Tried

This question : saying ReceiveTimeout=timespan doesn't seem to solve my problem.

Replacing pythoncom.Empty with pythoncom.Missing doesn't seem to work

This unanswered question seems very similar to mine

I found this article sending-msmq-messages-python

The article shows you how to send and receive a message using msmq. I don't understand why you can't just standard socket connection syntax to say if I haven't received a packet/connection then close connection

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

So something like that shouldn't be too difficult. Worst case scenario create a thread that checks every timeout_time if a variable is zero or not. If it's zero close queue nothing received if it's >0 set to zero and wait for more messages. I also found a GitHub about asynchronous msmq for python logging. asynchronous msmq This one just said receive while 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}')

Not the answer you wanted but one that will work.

In the original question's comments, @PeterBrittain suggested to try just using:

an integer (in milliseconds) for their timeout

I got around to trying that out, and actually, it worked! I found float values to work as well. Here is some sample Python code:

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

Thank you @PeterBrittain!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM