Python ที่ใช้งาน MessageQueue.Peek ผ่าน win32com จะทำให้หมดเวลาได้อย่างไร


9

สำหรับผู้เริ่มฉันอยากจะบอกว่าถ้าใครสามารถช่วยได้ที่นี่คุณก็เหลือเชื่อ

คำถามทั่วไป

โปรแกรม Python ของฉันต้องโต้ตอบกับ MSMQ โดยทั่วไปฉันต้องการที่จะมองไปที่คิวระบุการหมดเวลาหากไม่มีอะไรในคิว

อย่างไรก็ตามแม้จะมีความพยายามอย่างเต็มที่ แต่ก็ไม่สามารถ Peek () เพื่อรอช่วงเวลาหมดเวลาได้เมื่อไม่มีค่าในคิวก่อนหน้านี้ คุณช่วยชี้ให้เห็นสิ่งที่หายไปจากรหัสนี้ได้ไหม


รหัสปัจจุบันของฉัน

นี่คือรหัสของฉันตอนนี้:

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

ฉันวิ่ง: inspect.getfullargspec(queue.Peek)และรับ:

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

สิ่งที่ฉันได้ลอง

คำถามนี้การพูดReceiveTimeout=timespanดูเหมือนจะไม่สามารถแก้ปัญหาของฉันได้

การแทนที่pythoncom.Emptyด้วยpythoncom.Missingดูเหมือนจะไม่ทำงาน

คำถามที่ไม่มีคำตอบนี้ดูเหมือนว่าจะคล้ายกับฉันมาก


pythoncom CoWaitForMultipleHandles(Flags, Timeout , Handles )ช่วยคุณได้ไหม?
LinPy

สวัสดี @LinPy คุณมีความคิดอย่างละเอียดไหม? มันอาจช่วยได้ดูเหมือนว่าจะเป็นวิธีแก้ปัญหา ฉันสงสัยว่าจะทำให้เวลาถูกต้องได้queue.Peek
อย่างไร

1
แค่ความคิด แต่ตัวอย่างอื่น ๆ ที่ฉันได้เห็นจากอินเทอร์เฟซนี้ใน Python ก็แค่ใช้จำนวนเต็ม (หน่วยเป็นมิลลิวินาที) สำหรับการหมดเวลา บางที pywin32 ไม่ได้จัดการ TimeSpans อย่างที่คุณคาดหวัง ...
Brittain

@ PeterBrittain ขอขอบคุณนั่นจริง ๆ แล้วก็ทำเคล็ดลับ! ฉันโพสต์ความคิดเห็นของคุณเป็นคำตอบด้านล่าง
Intrastellar Explorer

คำตอบ:


0

ฉันพบบทความนี้ส่ง -msmq-messages-python

บทความแสดงวิธีการส่งและรับข้อความโดยใช้ msmq ฉันไม่เข้าใจว่าทำไมคุณไม่เพียงแค่ไวยากรณ์การเชื่อมต่อซ็อกเก็ตมาตรฐานเพื่อบอกว่าฉันยังไม่ได้รับแพ็คเก็ต / การเชื่อมต่อจากนั้นปิดการเชื่อมต่อ

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

ดังนั้นสิ่งที่ไม่ควรยากเกินไป สถานการณ์กรณีที่เลวร้ายที่สุดสร้างเธรดที่ตรวจสอบทุกครั้งที่ time__time หากตัวแปรมีค่าเป็นศูนย์หรือไม่ ถ้ามันเป็นคิวปิดศูนย์ไม่มีอะไรได้รับถ้ามัน> 0 ตั้งค่าเป็นศูนย์และรอข้อความเพิ่มเติม ฉันยังพบ GitHub เกี่ยวกับ asynchronous msmq สำหรับการบันทึก python asynchronous msmq อัน นี้เพิ่งได้รับในขณะที่ 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}')

ไม่ใช่คำตอบที่คุณต้องการ แต่เป็นคำตอบที่ใช้ได้


สวัสดี @MichaelHearn! ขอบคุณที่ให้การแก้ไขปัญหาที่มีประโยชน์หลายประการ เป็นเช่นนี้ฉันกำลังตัดสินคุณโปรดปราน :)
Intrastellar Explorer ที่

ขอบคุณ! @IntrastellarExplorer
Michael Hearn

0

ในความคิดเห็นของคำถามเดิม @PeterBrittain แนะนำให้ลองใช้:

จำนวนเต็ม (เป็นมิลลิวินาที) สำหรับการหมดเวลา

ฉันได้ลองแล้วและมันก็ใช้ได้จริง! ฉันพบfloatคุณค่าในการทำงานเช่นกัน นี่คือตัวอย่างโค้ดไพ ธ อน:

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

ขอบคุณ @PeterBrittain!

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.