Python menjalankan MessageQueue.Peek via win32com, bagaimana cara mendapatkan batas waktu yang tepat?

9

Sebagai permulaan, saya ingin mengatakan jika ada yang bisa membantu di sini, Anda luar biasa.

Pertanyaan Umum

Program Python saya perlu berinteraksi dengan MSMQ. Pada dasarnya, saya ingin mengintip antrian, menentukan batas waktu jika tidak ada dalam antrian.

Namun, terlepas dari upaya terbaik saya, saya tidak bisa meminta Peek () untuk menunggu interval waktu habis, ketika sebelumnya tidak ada nilai dalam antrian. Bisakah Anda tunjukkan apa yang hilang dari kode ini?


Kode Saat Ini Saya

Ini kode saya sekarang:

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

Saya menjalankan: inspect.getfullargspec(queue.Peek)dan mendapatkan:

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

Hal-hal yang Sudah Saya Coba

Pertanyaan ini : mengatakan ReceiveTimeout=timespansepertinya tidak menyelesaikan masalah saya.

Mengganti pythoncom.Emptydengan pythoncom.Missingsepertinya tidak berhasil

Pertanyaan yang belum terjawab ini tampaknya sangat mirip dengan pertanyaan saya

Penjelajah Intrastellar
sumber
pythoncom telah CoWaitForMultipleHandles(Flags, Timeout , Handles )membantu Anda?
LinPy
Hai @LinPy apakah Anda keberatan untuk menjelaskan? Ini mungkin membantu, sepertinya ini seperti solusi. Saya bertanya-tanya bagaimana cara mendapatkan args tepat untuk timeout onqueue.Peek
Intrastellar Explorer
1
Hanya sebuah pemikiran, tetapi contoh lain yang pernah saya lihat dari antarmuka ini di Python hanya menggunakan integer (dalam milidetik) untuk batas waktu mereka. Mungkin pywin32 tidak menangani TimeSpans seperti yang Anda harapkan ...
Peter Brittain
@PeterBrittain terima kasih, itu benar-benar berhasil! Saya memposting komentar Anda sebagai jawaban di bawah ini.
Intrastellar Explorer

Jawaban:

0

Saya menemukan artikel ini mengirim-msmq-messages-python

Artikel ini menunjukkan kepada Anda cara mengirim dan menerima pesan menggunakan msmq. Saya tidak mengerti mengapa Anda tidak bisa hanya sintaks koneksi soket standar untuk mengatakan jika saya belum menerima paket / koneksi maka tutup koneksi

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

Jadi sesuatu seperti itu seharusnya tidak terlalu sulit. Skenario kasus terburuk membuat utas yang memeriksa setiap timeout_time jika variabel nol atau tidak. Jika nol, tutup antrian tidak ada yang diterima jika itu> 0 diatur ke nol dan tunggu lebih banyak pesan. Saya juga menemukan GitHub tentang asinkron msmq untuk logging python. asynchronous msmq Yang ini baru saja berkata accept sementara 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}')

Bukan jawaban yang Anda inginkan tetapi yang akan berhasil.

Michael Hearn
sumber
Halo @MichaelHearn! Terima kasih telah menyediakan beberapa solusi yang berguna. Karena itu, saya menghadiahkan bounty kepada Anda :)
Intrastellar Explorer
Terima kasih! @IntrastellarExplorer
Michael Hearn
0

Dalam komentar pertanyaan aslinya, @PeterBrittain menyarankan untuk mencoba menggunakan:

integer (dalam milidetik) untuk batas waktu mereka

Saya sempat mencoba itu, dan sebenarnya, itu berhasil! Saya menemukan floatnilai-nilai untuk bekerja juga. Berikut ini beberapa contoh kode Python:

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

@PeterBrittain terima kasih!

Penjelajah Intrastellar
sumber