Python exécutant MessageQueue.Peek via win32com, comment obtenir le bon délai d'attente?

9

Pour commencer, je voudrais dire que si quelqu'un peut aider ici, vous êtes incroyable.

Question générale

Mon programme Python doit interagir avec MSMQ. Fondamentalement, je veux jeter un œil à une file d'attente, en spécifiant un délai d'attente s'il n'y a rien dans la file d'attente.

Cependant, malgré tous mes efforts, je ne peux pas faire en sorte que Peek () attende l'intervalle de temporisation, quand il n'y a aucune valeur précédemment dans la file d'attente. Pouvez-vous s'il vous plaît souligner ce qui manque à ce code?


Mon code actuel

Voici mon code en ce 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

Je cours: inspect.getfullargspec(queue.Peek)et j'obtiens:

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

Les choses que j'ai essayées

Cette question : dire ReceiveTimeout=timespanne semble pas résoudre mon problème.

Remplacer pythoncom.Emptypar pythoncom.Missingne semble pas fonctionner

Cette question sans réponse semble très similaire à la mienne

Explorateur intrastellaire
la source
pythoncom CoWaitForMultipleHandles(Flags, Timeout , Handles )vous aide-t-il?
LinPy
Bonjour @LinPy, ça vous dérange d'élaborer? Cela peut aider, mais cela semble être une solution de contournement. Je me demande comment obtenir des queue.Peek
arguments corrects
1
Juste une pensée, mais d'autres exemples que j'ai vus de cette interface en Python utilisent simplement un entier (en millisecondes) pour leur timeout. Peut-être que pywin32 ne gère pas les TimeSpans comme vous vous attendez ...
Peter Brittain
@PeterBrittain merci, ça a vraiment fait l'affaire! J'ai posté votre commentaire comme réponse ci-dessous.
Intrastellar Explorer

Réponses:

0

J'ai trouvé cet article envoyant-msmq-messages-python

L'article vous montre comment envoyer et recevoir un message à l'aide de msmq. Je ne comprends pas pourquoi vous ne pouvez pas simplement utiliser une syntaxe de connexion de socket standard pour dire si je n'ai pas reçu de paquet / connexion, puis fermer la connexion

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

Donc quelque chose comme ça ne devrait pas être trop difficile. Dans le pire des cas, créez un thread qui vérifie à chaque timeout_time si une variable est nulle ou non. Si c'est zéro fermer la file d'attente rien n'est reçu si c'est> 0 mis à zéro et attendre plus de messages. J'ai également trouvé un GitHub sur msmq asynchrone pour la journalisation python. msmq asynchrone Celui-ci vient de dire recevoir alors que 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}')

Pas la réponse que vous vouliez, mais celle qui fonctionnera.

Michael Hearn
la source
Bonjour @MichaelHearn! Merci d'avoir fourni plusieurs solutions de contournement utiles. En tant que tel, je vous attribue la prime :)
Explorateur intrastellaire
Je vous remercie! @IntrastellarExplorer
Michael Hearn
0

Dans les commentaires de la question d'origine, @PeterBrittain a suggéré d'essayer simplement d'utiliser:

un entier (en millisecondes) pour leur délai d'expiration

Je me suis mis à essayer ça, et en fait, ça a marché! J'ai trouvé que les floatvaleurs fonctionnaient aussi. Voici quelques exemples de code Python:

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

Merci @PeterBrittain!

Explorateur intrastellaire
la source