Python executando MessageQueue.Peek via win32com, como obter o tempo limite certo?


9

Para começar, eu gostaria de dizer que se alguém puder ajudar aqui, você é incrível.

Pergunta Geral

Meu programa Python precisa interagir com o MSMQ. Basicamente, quero espiar uma fila, especificando um tempo limite se não houver nada na fila.

No entanto, apesar dos meus melhores esforços, não consigo Peek () aguardar o intervalo de tempo limite, quando não há valor anteriormente na fila. Você pode apontar o que está faltando nesse código?


Meu Código Atual

Aqui está o meu código agora:

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

Eu corro: inspect.getfullargspec(queue.Peek)e recebo:

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

Coisas que eu tentei

Esta pergunta : dizer ReceiveTimeout=timespannão parece resolver o meu problema.

Substituir pythoncom.Emptypor pythoncom.Missingnão parece funcionar

Esta pergunta sem resposta parece muito semelhante à minha


pythoncom tem CoWaitForMultipleHandles(Flags, Timeout , Handles )isso ajuda você?
— LinPy 5/11/19

Oi @LinPy, você se importa em elaborar? Pode ajudar, mas parece uma solução alternativa. Eu estou querendo saber como obter args certo para tempo limite emqueue.Peek
— intrastellar Explorador

11
Apenas um pensamento, mas outros exemplos que eu vi dessa interface no Python simplesmente usam um número inteiro (em milissegundos) para o tempo limite. Talvez pywin32 não está a lidar com TimeSpans da maneira esperada ...
— Peter Brittain

@ PeterBrittain obrigado, que realmente fez o truque! Publiquei seu comentário como resposta abaixo.
— Explorer Intrastellar

Respostas:


0

Encontrei este artigo enviando-msmq-messages-python

O artigo mostra como enviar e receber uma mensagem usando o msmq. Eu não entendo por que você não pode simplesmente sintaxe de conexão de soquete padrão para dizer se eu não recebi um pacote / conexão e fechei a conexão

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

Então, algo assim não deve ser muito difícil. No pior cenário, crie um encadeamento que verifique a cada timeout_time se uma variável é zero ou não. Se for zero, feche a fila, nada será recebido se for> 0 definido como zero e aguarde mais mensagens. Eu também encontrei um GitHub sobre msmq assíncrono para log em python. msmq assíncrono Este disse apenas receber enquanto 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}')

Não é a resposta que você queria, mas uma que funcione.


Olá @MichaelHearn! Obrigado por fornecer várias soluções úteis. Como tal, estou concedendo-lhe a recompensa :)
— intrastellar Explorador

Obrigado! @IntrastellarExplorer
— Michael Hearn

0

Nos comentários da pergunta original, @PeterBrittain sugeriu tentar apenas usar:

um número inteiro (em milissegundos) para o tempo limite

Eu tentei fazer isso e, na verdade, funcionou! Encontrei floatvalores para trabalhar também. Aqui está um exemplo de código Python:

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

Obrigado @PeterBrittain!

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.