(Python 3)
我正在使用Python生成器从队列中读取消息。
在使用者读取队列消息之后,如果成功处理了队列消息,它需要能够告诉生成器删除队列消息。
为了将.send()发送到Python生成器,似乎我必须先将.send(None)发送给生成器。这使得我的代码比我想象的要胖。
任何人都可以建议qconsumer.py以更少的代码行驱动生成器吗?我已经确定了我希望消除的下面哪些行。
简而言之,我如何使下面的代码更紧凑,有关如何删除行的任何建议?
以下代码是qconsumer.py:
from qserver import Qserver
myqserver = Qserver()
myproducer = myqserver.producer() # trying to eliminate this line
# first send to a generator must be None
myproducer.send(None) # trying to eliminate this line
for msg in myproducer:
# do something with message
print(msg)
if messageprocessok:
myproducer.send('delete')
以下代码是qserver.py:
# -*- coding: utf-8 -*-
import boto
from boto.sqs.connection import SQSConnection
from boto.sqs.message import Message
QNAME = 'qinbound'
SQSREGION = 'us-west-1'
class Qserver():
"""A simple Q server."""
def __init__(self, qname=None, sqsregion=None):
self.qname = qname or QNAME
self.sqsregion = sqsregion or SQSREGION
self.sqsconn = boto.sqs.connect_to_region(self.sqsregion)
self.q_in = self.sqsconn.get_queue(self.qname)
def producer(self):
while True:
qmessage = self.q_in.read(wait_time_seconds=20)
if qmessage is None:
continue
action = (yield qmessage.get_body())
if action == 'delete':
# if processing completed ok, clear message from this queue
self.q_in.delete_message(qmessage)
答案 0 :(得分:2)
您当前的消费者正在丢弃消息,因为每个send
调用都返回一个消息。你应该这样做:
myqserver = Qserver()
myproducer = myqserver.producer()
messageprocessok = False
while True:
msg = myproducer.send('delete' if messageprocessok else None)
# do something with message
print(msg)
或者:
myqserver = Qserver()
myproducer = myqserver.producer()
msg = next(myproducer)
while True:
# do something with message
print(msg)
msg = myproducer.send('delete' if messageprocessok else None)
您需要单独调用Qserver()
和myqserver.producer()
,这仅仅是因为您将prouducer
作为类的方法。或者,您可以使用独立函数,或者创建一个只返回Qserver().producer()
的包装函数。这是独立版本:
def producer(qname=None, sqsregion=None):
qname = qname or QNAME
sqsregion = sqsregion or SQSREGION
sqsconn = boto.sqs.connect_to_region(sqsregion)
q_in = sqsconn.get_queue(qname)
while True:
qmessage = q_in.read(wait_time_seconds=20)
if qmessage is None:
continue
action = (yield qmessage.get_body())
if action == 'delete':
# if processing completed ok, clear message from this queue
q_in.delete_message(qmessage)
答案 1 :(得分:1)
了解了你要做的事情后,我想我会避免将send
与迭代混合。将myqserver
类作为迭代器本身似乎对我更有意义:
# -*- coding: utf-8 -*-
import boto
from boto.sqs.connection import SQSConnection
from boto.sqs.message import Message
QNAME = 'qinbound'
SQSREGION = 'us-west-1'
class Qserver():
"""A simple Q server."""
_current_message = None
def __init__(self, qname=None, sqsregion=None):
self.qname = qname or QNAME
self.sqsregion = sqsregion or SQSREGION
self.sqsconn = boto.sqs.connect_to_region(self.sqsregion)
self.q_in = self.sqsconn.get_queue(self.qname)
def __iter__(self):
return self
def __next__(self):
while True:
qmessage = self.q_in.read(wait_time_seconds=20)
if qmessage is not None:
self._current_message = qmessage
return qmessage
next = __next__
def delete_current(self):
if self._current_message is not None:
self.q_in.delete_message(self._current_message)
用法如下:
from qserver import Qserver
myqserver = Qserver()
for msg in myqserver:
# do something with message
print(msg)
if messageprocessok:
myqserver.delete_current()