信号处理 pika / python
我在一个消费者中使用了 pika.BlockingConnection
,这个消费者会对每条消息执行一些任务。我还添加了信号处理,这样消费者在完成所有任务后可以正常退出。
当我处理消息时,如果收到信号,我只会从函数中得到 "signal received"
的提示,但代码并没有退出。因此,我决定在回调函数的末尾也检查一下是否收到信号。我的问题是,我需要检查信号多少次,因为代码中会有很多其他函数。有没有更好的方法来处理信号,而不至于检查得太频繁呢?
import signal
import sys
import pika
from time import sleep
received_signal = False
all_over = False
def signal_handler(signal, frame):
global received_signal
print "signal received"
received_signal = True
signal.signal(signal.SIGINT, signal_handler)
signal.signal(signal.SIGTERM, signal_handler)
mq_connection = pika.BlockingConnection(pika.ConnectionParameters(my_mq_server, virtual_host='test'))
mq_channel = mq_connection.channel()
def callback(ch, method, properties, body):
if received_signal:
print "Exiting, as a kill signal is already received"
exit(0)
print body
sleep(50)
mq_channel.basic_ack(delivery_tag=method.delivery_tag)
print "Message consumption complete"
if received_signal:
print "Exiting, as a kill signal is already received"
exit(0)
try:
print ' [*] Waiting for messages. To exit press CTRL+C'
mq_channel.basic_consume(callback, queue='test')
mq_channel.start_consuming()
except Exception:
mq_channel.close()
exit()
这是我在这里的第一个问题,如果需要更多细节,请告诉我。
1 个回答
4
我觉得这个可以满足你的需求:
#!/usr/bin/python
import signal
import sys
import pika
from contextlib import contextmanager
received_signal = False
processing_callback = False
def signal_handler(signal, frame):
global received_signal
print "signal received"
received_signal = True
if not processing_callback:
sys.exit()
signal.signal(signal.SIGINT, signal_handler)
signal.signal(signal.SIGTERM, signal_handler)
@contextmanager
def block_signals():
global processing_callback
processing_callback = True
try:
yield
finally:
processing_callback = False
if received_signal:
sys.exit()
def callback(ch, method, properties, body):
with block_signals:
print body
sum(xrange(0, 200050000)) # sleep gets interrupted by signals, this doesn't.
mq_channel.basic_ack(delivery_tag=method.delivery_tag)
print "Message consumption complete"
if __name__ == "__main__":
try:
mq_connection = pika.BlockingConnection(pika.ConnectionParameters('localhost'))
mq_channel = mq_connection.channel()
print ' [*] Waiting for messages. To exit press CTRL+C'
mq_channel.basic_consume(callback, queue='test')
mq_channel.start_consuming()
except Exception as e:
mq_channel.close()
sys.exit()
我使用了一个上下文管理器来处理信号的阻塞,这样所有的逻辑就隐藏在回调函数之外了。这也应该让代码更容易重复使用。为了让你更清楚它是怎么工作的,它其实和这个是一样的:
def callback(ch, method, properties, body):
global processing_callback
processing_callback = True
try:
print body
sum(xrange(0, 200050000))
mq_channel.basic_ack(delivery_tag=method.delivery_tag)
print "Message consumption complete"
finally:
processing_callback = False
if received_signal:
sys.exit()