原文地址:http://www.screeley.com/entries/2009/jun/07/django-daemon-command-extension/
Recently I started to move Cubby Scott away from a cron and towards a queue. It's hard to be real time when you wake up a cron job once every 3 minutes. Lame. I'm also in the process of adding screenshots and content retrieval. Both take a good amount of time to process. The queue part was easy after reading Rabbits and Warrens and Working with Python and RabbitMQ . The problem came when I started working on the consumer, no one ever talks about the consumer. Well I'm going to give the consumer some love.
The consumer should be a daemon, but what's the best way to do that? It would be nice if I could just use Django's built in management functions rather than having one off scripts. i.e:
python manage.py linkconsumer
I would run that once when I started up the server and be good to go. It turned out to be pretty easy with python-daemon . I threw together a quick class to handle it and you can get a copy of the DaemonCommand here . All it really does is create an interface for a daemon context and open it. When subclassing the DaemonCommand instead of calling handle
use handle_daemon
.
Carrot is the open source project that ties the two together, but was a little too complex. So for the purpose of keeping it simple stupid, I used Nathan Borror 's Flopsy . Dead simple way to communicate with a queue.
If we put that together we accomplish our goal in 20 lines of code.
from daemonextension import DaemonCommand from django.conf import settings import os class Command(DaemonCommand): #Declare Daemon std. stdout = os.path.join(settings.DIRNAME, "log/cubbyscott.out") stderr = os.path.join(settings.DIRNAME, "log/cubbyscott.err") pidfile = os.path.join(settings.DIRNAME, "pid/cb_link.err") def handle_daemon(self, *args, **options): from flopsy import Connection, Consumer consumer = Consumer(connection=Connection()) consumer.declare(queue='links', exchange='cubbyscott', routing_key='importer', auto_delete=False) def message_callback(message): print 'Recieved: ' + message.body consumer.channel.basic_ack(message.delivery_tag) consumer.register(message_callback) consumer.wait()