Python esegue MessageQueue.Peek tramite win32com, come ottenere il timeout giusto?


9

Per i principianti, vorrei dire che se qualcuno può aiutare qui, sei incredibile.

Domanda generale

Il mio programma Python deve interagire con MSMQ. Fondamentalmente, voglio sbirciare una coda, specificando un timeout se non c'è nulla nella coda.

Tuttavia, nonostante i miei migliori sforzi, non riesco a far attendere a Peek () l'intervallo di timeout, quando in precedenza non è presente alcun valore nella coda. Potete per favore sottolineare ciò che manca a questo codice?


Il mio codice attuale

Ecco il mio codice adesso:

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

Corro: inspect.getfullargspec(queue.Peek)e ottengo:

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

Cose che ho provato

Questa domanda : dire ReceiveTimeout=timespannon sembra risolvere il mio problema.

La sostituzione pythoncom.Emptycon pythoncom.Missingnon sembra funzionare

Questa domanda senza risposta sembra molto simile alla mia


pythoncom CoWaitForMultipleHandles(Flags, Timeout , Handles )ti aiuta?
LinPy,

Ciao @LinPy ti dispiace elaborare? Può essere d'aiuto, in qualche modo sembra una soluzione alternativa. Mi chiedo come ottenere argomenti adatti per il timeoutqueue.Peek
Intrastellar Explorer

1
Solo un pensiero, ma altri esempi che ho visto di questa interfaccia in Python usano semplicemente un numero intero (in millisecondi) per il loro timeout. Forse pywin32 non sta gestendo TimeSpans come ti aspetti ...
Peter Brittain,

@PeterBrittain grazie, che in realtà ha fatto il trucco! Ho pubblicato il tuo commento come risposta di seguito.
Intrastellar Explorer

Risposte:


0

Ho trovato questo articolo send-msmq-message-python

L'articolo mostra come inviare e ricevere un messaggio usando msmq. Non capisco perché non si può semplicemente sintassi della connessione socket standard per dire se non ho ricevuto un pacchetto / connessione quindi chiudere la connessione

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

Quindi qualcosa del genere non dovrebbe essere troppo difficile. Lo scenario peggiore crea un thread che controlla ogni timeout_time se una variabile è zero o no. Se la coda di chiusura è zero, non viene ricevuto nulla se è> 0 impostato su zero e attendere altri messaggi. Ho anche trovato un GitHub su msmq asincrono per la registrazione di Python. msmq asincrono Questo ha appena detto ricevere mentre 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}')

Non la risposta che volevi, ma una che funzionerà.


Ciao @MichaelHearn! Grazie per aver fornito diverse soluzioni utili. Come tale, ti sto assegnando la generosità :)
Intrastellar Explorer l'

Grazie! @IntrastellarExplorer
Michael Hearn,

0

Nei commenti della domanda originale, @PeterBrittain ha suggerito di provare a usare solo:

un numero intero (in millisecondi) per il loro timeout

Ho provato a provarlo, e in realtà ha funzionato! Ho trovato anche floatvalori per funzionare. Ecco alcuni esempi di codice Python:

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

Grazie @ PeterBrittain!

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.