信号处理pika/python
我正在消费者中使用信号处理pika/python,python,signals,signal-handling,pika,Python,Signals,Signal Handling,Pika,我正在消费者中使用pika.BlockingConnection,该消费者为每条消息执行一些任务。我还添加了信号处理,以便消费者在完成所有任务后正确死亡 在处理消息和接收信号时,我只从函数中获取“signal received”,但代码不退出。所以,我决定检查在回调函数末尾接收到的信号。问题是,我需要检查信号多少次,因为代码中还有很多函数。有没有更好的方法来处理信号而不做过火的事情 import signal import sys import pika from time import sle
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()
这是我在这里的第一个问题,如果需要更多详细信息,请告诉我。我想这正是您想要的:
#!/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()
我使用了contextmanager来处理阻塞信号,因此所有逻辑都隐藏在回调本身之外。这也会使代码的重用变得更容易。为了说明它是如何工作的,它相当于:
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()
当前代码将吞下SIGTERM或SIGINT,直到通过队列接收到下一条消息,此时它应该退出。这真的是你想要的吗?为什么不让
signal\u handler
方法直接调用sys.exit(0)
呢?我希望信号处理可以通过两种方式完成:1)在等待消息时,它应该死掉;2)在使用消息时,它应该完成当前的工作,然后死掉。我当前的代码包含第二个条件,但不是第一个条件。这就是问题所在。这有可能吗?是的,有可能。我将添加一个答案。使用xrange而不是range,否则您的内存将爆炸,当它翻页到磁盘时,它将开始颠簸。