Python通过win32com运行MessageQueue.Peek,如何正确设置超时时间?


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.Emptypythoncom.Missing似乎并不工作

这个未解决的问题似乎与我的非常相似


pythoncom有CoWaitForMultipleHandles(Flags, Timeout , Handles )帮助吗?
LinPy

嗨@LinPy你介意吗?它可能会有所帮助,尽管这似乎是一种解决方法。我想知道如何使args正确超时queue.Peek
Intrastellar Explorer

1
只是一个想法,但我在Python中看到的有关此接口的其他示例仅使用整数(以毫秒为单位)作为其超时时间。也许pywin32不能按您期望的方式处理TimeSpans ...
Peter Brittain

@PeterBrittain谢谢您,实际上可以解决问题!我在以下答案中发表了您的评论。
星际探险家

Answers:


0

我发现这篇文章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设置为零,则什么也没有收到,并等待更多消息。我还找到了一个有关异步msmq的python日志记录的GitHub。 异步msmq 这只是说接收而True 下降7 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!感谢您提供多种有用的解决方法。因此,我授予您赏金:)
星际探险家

谢谢!@IntrastellarExplorer
Michael Hearn

0

在原始问题的评论中,@ PeterBrittain建议尝试仅使用:

超时的整数(以毫秒为单位)

我设法尝试一下,实际上,它起作用了!我发现float价值观也起作用。这是一些示例Python代码:

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

谢谢@PeterBrittain!

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.