penso che questo fa quello che stai cercando:
#!/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()
ho usato un contextmanager per gestire bloccando i segnali, in modo che tutta la logica è nascosto al di fuori della richiamata stessa. Questo dovrebbe anche rendere più facile il riutilizzo del codice. Giusto per chiarire come si sta lavorando, è equivalente a questo:
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()
Il codice attuale ingoiare SIGTERM o SIGINT fino alla ricezione del messaggio successivo tramite la coda, a quel punto dovrebbe uscire. È in realtà quello che vuoi? Perché non usare il metodo 'signal_handler' per chiamare direttamente' sys.exit (0) '? – dano
Desidero che la gestione del segnale avvenga in due modi: 1) Durante l'attesa dei messaggi, dovrebbe semplicemente morire 2) Mentre consuma un messaggio, dovrebbe completare il lavoro corrente e quindi morire. Il mio codice corrente incorpora la seconda condizione, ma non la prima. Questo è il problema. Sarebbe anche possibile? – user3295878
Sì, è possibile. Aggiungerò una risposta – dano