Topic exchange is powerful and can behave like other exchanges.
When a queue is bound with #
(hash) binding key - it will receive
all the messages, regardless of the routing key - like in fanout
exchange.
When special characters *
(star) and #
(hash) aren't used in bindings,
the topic exchange will behave just like a direct
one.
We're going to use a topic
exchange in our logging system. We'll
start off with a working assumption that the routing keys of logs will
have two words: <facility>.<severity>
.
The code is almost the same as in the previous tutorial.
emit_log_topic.py
(source)
#!/usr/bin/env python
import pika
import sys
connection = pika.BlockingConnection(
pika.ConnectionParameters(host='localhost'))
channel = connection.channel()
channel.exchange_declare(exchange='topic_logs', exchange_type='topic')
routing_key = sys.argv[1]iflen(sys.argv)>2else'anonymous.info'
message =' '.join(sys.argv[2:])or'Hello World!'
channel.basic_publish(
exchange='topic_logs', routing_key=routing_key, body=message)
print(f" [x] Sent {routing_key}:{message}")
connection.close()
receive_logs_topic.py
(source)
#!/usr/bin/env python
import pika
import sys
connection = pika.BlockingConnection(
pika.ConnectionParameters(host='localhost'))
channel = connection.channel()
channel.exchange_declare(exchange='topic_logs', exchange_type='topic')
result = channel.queue_declare('', exclusive=True)
queue_name = result.method.queue
binding_keys = sys.argv[1:]
ifnot binding_keys:
sys.stderr.write("Usage: %s [binding_key]...\n"% sys.argv[0])
sys.exit(1)
for binding_key in binding_keys:
channel.queue_bind(
exchange='topic_logs', queue=queue_name, routing_key=binding_key)
print(' [*] Waiting for logs. To exit press CTRL+C')
defcallback(ch, method, properties, body):
print(f" [x] {method.routing_key}:{body}")
channel.basic_consume(
queue=queue_name, on_message_callback=callback, auto_ack=True)
channel.start_consuming()
To receive all the logs run:
python receive_logs_topic.py "#"
To receive all logs from the facility kern
:
python receive_logs_topic.py "kern.*"
Or if you want to hear only about critical
logs:
python receive_logs_topic.py "*.critical"
You can create multiple bindings:
python receive_logs_topic.py "kern.*""*.critical"
And to emit a log with a routing key kern.critical
type:
python emit_log_topic.py "kern.critical""A critical kernel error"
Have fun playing with these programs. Note that the code doesn't make any assumption about the routing or binding keys, you may want to play with more than two routing key parameters.
Move on to tutorial 6 to learn about RPC.