win32comを介してMessageQueue.Peekを実行しているPython、タ​​イムアウトを正しく取得するにはどうすればよいですか?


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を期待どおりに処理していないのかもしれません...
Peter Brittain

@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の場合は何も受信されず、ゼロに設定されて、さらにメッセージを待ちます。Pythonロギングの非同期msmqに関するGitHubも見つかりました。 非同期の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 '11 / 11/19

ありがとうございました!@IntrastellarExplorer
Michael Hearn

0

元の質問のコメントでは、@ PeterBrittainが次のように使用することを提案しています:

タイムアウトの整数(ミリ秒)

私はそれを試してみることにしました、そして実際には、それはうまくいきました!float値も機能することがわかりました。Pythonコードのサンプルを以下に示します。

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

@PeterBrittainありがとうございます!

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.