Python, auf dem MessageQueue.Peek über win32com ausgeführt wird, wie kann das Timeout richtig eingestellt werden?

9

Für den Anfang möchte ich sagen, wenn jemand hier helfen kann, sind Sie unglaublich.

Allgemeine Frage

Mein Python-Programm muss mit MSMQ interagieren. Grundsätzlich möchte ich einen Blick auf eine Warteschlange werfen und eine Zeitüberschreitung angeben, wenn sich nichts in der Warteschlange befindet.

Trotz meiner Bemühungen kann ich Peek () nicht dazu bringen, das Timeout-Intervall abzuwarten, wenn sich zuvor kein Wert in der Warteschlange befindet. Können Sie bitte darauf hinweisen, was in diesem Code fehlt?


Mein aktueller Code

Hier ist mein Code im Moment:

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

Ich renne: inspect.getfullargspec(queue.Peek)und bekomme:

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

Dinge, die ich versucht habe

Diese Frage : Sprichwort ReceiveTimeout=timespanscheint mein Problem nicht zu lösen.

Das Ersetzen pythoncom.Emptydurch pythoncom.Missingscheint nicht zu funktionieren

Diese unbeantwortete Frage scheint meiner sehr ähnlich zu sein

Intrastellar Explorer
quelle
Pythoncom hat CoWaitForMultipleHandles(Flags, Timeout , Handles )es hilft Ihnen?
LinPy
Hallo @LinPy, macht es Ihnen etwas aus? Es kann helfen, aber es scheint eine Art Workaround zu sein. Ich frage mich, wie ich Argumente für Timeout aufqueue.Peek
Intrastellar Explorer
1
Nur ein Gedanke, aber andere Beispiele, die ich von dieser Schnittstelle in Python gesehen habe, verwenden einfach eine Ganzzahl (in Millisekunden) für ihre Zeitüberschreitung. Vielleicht behandelt pywin32 TimeSpans nicht so, wie Sie es erwarten ...
Peter Brittain
@ PeterBrittain danke, das hat tatsächlich den Trick gemacht! Ich habe Ihren Kommentar als Antwort unten gepostet.
Intrastellar Explorer

Antworten:

0

Ich habe diesen Artikel gefunden , der-msmq-messages-python sendet

Der Artikel zeigt Ihnen, wie Sie mit msmq eine Nachricht senden und empfangen. Ich verstehe nicht, warum Sie nicht einfach die Standard-Socket-Verbindungssyntax verwenden können, um zu sagen, wenn ich kein Paket / keine Verbindung erhalten habe, schließen Sie die Verbindung

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

So etwas sollte also nicht zu schwierig sein. Im schlimmsten Fall wird ein Thread erstellt, der jedes Mal überprüft, ob eine Variable Null ist oder nicht. Wenn die Warteschlange Null ist, wird nichts empfangen, wenn> 0 auf Null gesetzt ist, und auf weitere Nachrichten warten. Ich habe auch einen GitHub über asynchrones msmq für die Python-Protokollierung gefunden. asynchrones msmq Dieser hat gerade gesagt, dass er empfangen wird, während 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}')

Nicht die Antwort, die Sie wollten, aber eine, die funktionieren wird.

Michael Hearn
quelle
Hallo @MichaelHearn! Vielen Dank, dass Sie mehrere nützliche Problemumgehungen bereitgestellt haben. Als solches
vergebe
Vielen Dank! @IntrastellarExplorer
Michael Hearn
0

In den Kommentaren der ursprünglichen Frage schlug @PeterBrittain vor, nur Folgendes zu verwenden:

eine Ganzzahl (in Millisekunden) für ihre Zeitüberschreitung

Ich habe das ausprobiert und tatsächlich hat es funktioniert! Ich fand auch floatWerte, die funktionieren. Hier ist ein Beispiel für einen Python-Code:

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

Vielen Dank, dass Sie @PeterBrittain!

Intrastellar Explorer
quelle