简体   繁体   English

Python 通过 win32com 运行 MessageQueue.Peek,如何获得超时?

[英]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.我的 Python 程序需要与 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.但是,尽管我尽了最大努力,但当队列中没有任何值时,我无法让 Peek() 等待超时间隔。 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:我运行: 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={})

Things I've Tried我尝试过的事情

This question : saying ReceiveTimeout=timespan doesn't seem to solve my problem. 这个问题:说ReceiveTimeout=timespan似乎并不能解决我的问题。

Replacing pythoncom.Empty with pythoncom.Missing doesn't seem to workpythoncom.Missing替换pythoncom.Empty似乎不起作用

This unanswered question seems very similar to mine 这个未回答的问题似乎与我的非常相似

I found this article sending-msmq-messages-python我发现这篇文章正在发送-msmq-messages-python

The article shows you how to send and receive a message using msmq.本文向您展示了如何使用 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.最坏的情况是创建一个线程检查每个 timeout_time 变量是否为零。 If it's zero close queue nothing received if it's >0 set to zero and wait for more messages.如果它是零关闭队列,如果它 >0 设置为零并等待更多消息,则没有收到任何消息。 I also found a GitHub about asynchronous msmq for python logging.我还发现了一个关于用于 python 日志记录的异步 msmq 的 GitHub。 asynchronous msmq This one just said receive while True dlopes7 msmq 异步msmq这个刚刚说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:在原始问题的评论中,@PeterBrittain 建议尝试仅使用:

an integer (in milliseconds) for their timeout超时的 integer(以毫秒为单位)

I got around to trying that out, and actually, it worked!我开始尝试这个,实际上,它奏效了! I found float values to work as well.我发现float值也可以工作。 Here is some sample Python code:这是一些示例 Python 代码:

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

Thank you @PeterBrittain!谢谢@PeterBrittain!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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