Leading b in python pika response - python

I am trying to make a simple AMQP client using python. I copied the code I found in RabbitMQ website:
#!/usr/bin/env python
import pika
connection = pika.BlockingConnection(pika.ConnectionParameters(
host='localhost'))
channel = connection.channel()
channel.queue_declare(queue='hello')
def callback(ch, method, properties, body):
print(" [x] Received %r" % body)
channel.basic_consume(callback,
queue='hello',
no_ack=True)
print(' [*] Waiting for messages. To exit press CTRL+C')
channel.start_consuming()
This works except It always prints something like [x] Received b'my message'. Due to this I cant parse my json messages. How do I fix this ?

You may use decode() to convert the string to utf-8 and then print it out, something like
str = 'your str'
print(str.decode())

Adding to yichucai's correct answer, I found that you can add the decode() method directly to the body var inside print. Like so:
print(" [x] Received %r" % body.decode())

Related

TypeError got multiple values for keyword argument queue

I am stuck at this error that I am not managing to fix. I have found relevant cases, but I am having a hard time applying it to my own problem.
Can someone help me understand why this Typerror happens and / or help me find a solution? (please respnd to me as a beginner)
I am using python in a raspberry pi and pika 1.1.0.
this is my traceback:
File "amqp.py", line 33, in <module>
no_ack=True)
TypeError: basic_consume() got multiple values for keyword argument 'queue
this what I think is the relevant code:
def callback(ch, method, properties, body):
printer.inverseOn()
printer.println(' ' + '{:<31}'.format("TXT MESSAGE"))
printer.inverseOff()
printer.println(body)
printer.feed(3)
print("complete")
print " [x] Received %r" % (body)
channel.basic_consume(callback,
queue='texts',
no_ack=True)
and this is the rest of the .py if interesting
try:
from urllib.parse import urlparse
except ImportError:
from urlparse import urlparse
import pika, os, sys
from Adafruit_Thermal import *
printer = Adafruit_Thermal("/dev/serial0", 19200, timeout=5)
url_str = os.environ.get('CLOUDAMQP_URL','amqp://xxxxx')
url = urlparse(url_str)
params = pika.ConnectionParameters(host=url.hostname, virtual_host=url.path[1:],
credentials=pika.PlainCredentials(url.username, url.password))
connection = pika.BlockingConnection(params)
channel = connection.channel()
channel.queue_declare(queue='texts')
def callback(ch, method, properties, body):
printer.inverseOn()
printer.println(' ' + '{:<31}'.format("TXT MESSAGE"))
printer.inverseOff()
printer.println(body)
printer.feed(3)
print("complete")
print " [x] Received %r" % (body)
channel.basic_consume(callback,
queue='texts',
no_ack=True)
try:
channel.start_consuming()
except KeyboardInterrupt:
print "Break detected"
channel.stop_consuming()
connection.close()
sys.exit()
Not sure which pika version you're using; but according to [1], the callback parameter is the 2nd one. The queue parameter is first. i.e.
channel.basic_consume("texts", callback, no_ack=True)
[1] - https://pika.readthedocs.io/en/stable/modules/adapters/blocking.html#pika.adapters.blocking_connection.BlockingChannel

Calling more than one functions as RABBITMQ message

I am just starting to use RabbitMQ and Python in general. I have been reading the tuts on the rabbit official page, but I have no idea how to use Rabbitmq to do another things.
I have been trying to run the example of this [tutorial] (https://www.rabbitmq.com/tutorials/tutorial-three-python.html), It runs well,.. BUT I need to know how can I create more than one fucntions and call them throug Rabbitmq Messages?... (I am also using this [example] (Python and RabbitMQ - Best way to listen to consume events from multiple channels?) to guide me. )
I hope someone have some idea how to do this... (I will repeat again, I am very new on this topics)...
This some code what i have.
I use this code to send the message as the tutorial..
import pika
import sys
url = 'amqp://oamogcgg:xxxxxxxxxxxxxxxxxxxxxxxxx#salamander.rmq.cloudamqp.com/oamogcgg'
params = pika.URLParameters(url)
connection = pika.BlockingConnection(params)
channel = connection.channel()
channel.exchange_declare(exchange='logs', exchange_type='fanout')
message = ' '.join(sys.argv[1:]) or "info: THIS IS A TEST MESSAGE !!!!!!"
channel.basic_publish(exchange='logs', routing_key='', body=message)
print(" [x] Sent %r" % message)
connection.close()
And in this file is where I receive the message according to me.
import pika
import sys
import threading
threads=[]
#function 1
def validator1(channel):
channel.queue_declare(queue='queue_name')
print (' [*] Waiting messsaes for valiadtor1 press CTRL+C')
def callback(ch, method, properties, body):
print (" Received %s" % (body))
sleep(2) #I need stop it for two minutes
channel.basic_consume(callback, queue='queue_name', no_ack=True)
channel.start_consuming()
#function 2
def validator2(channel):
channel.queue_declare(queue='queue_name')
print (' [*] Waiting messsaes for valiadtor2 press CTRL+C')
def callback(ch, method, properties, body):
print (" Received %s" % (body))
sleep(2) #I need stop it for two minutes
channel.basic_consume(callback, queue='queue_name', no_ack=True)
channel.start_consuming()
def manager():
url = 'amqp://oamogcgg:xxxxxxxxxxxxxxxxxxxxxxxxx#salamander.rmq.cloudamqp.com/oamogcgg'
params = pika.URLParameters(url)
#channel 1
connection1= pika.BlockingConnection(params)
channel1 = connection1.channel()
channel1.exchange_declare(exchange='logs', exchange_type='fanout')
result = channel1.queue_declare(queue='', exclusive=True)
queue_name = result.method.queue
channel1.queue_bind(exchange='logs', queue=queue_name)
#channel 2
connection2= pika.BlockingConnection(params)
channel2 = connection2.channel()
channel2.exchange_declare(exchange='logs', exchange_type='fanout')
result = channel2.queue_declare(queue='', exclusive=True)
queue_name = result.method.queue
channel2.queue_bind(exchange='logs', queue=queue_name)
#creating threads
t1 = threading.Thread(target=validator1, args=(channel1,))
t1.daemon = True
threads.append(t1)
t1.start()
t2 = threading.Thread(target=valiadtor2, args=(channel2,))
t2.daemon = True
threads.append(t2)
t2.start()
for t in threads:
t.join()
manager()
If your functions are dependent(by dependent I mean, one function works on the output of the other) then, you can call all those functions one by one in your callback function. Once the last function is executed successfully you can acknowledge the message.
If those functions are independent then you can maintain multiple queues for each of the function you wanna execute on the message. The same message can be routed to multiple queues using a fanout exchange as mentioned in RabbitMQ Tutorial-3.

RabbitMQ basic publish

I have RabbitMQ listener written in Python from examples from rabbitmq's docs:
#!/usr/bin/env python
import time
import pika
connection = pika.BlockingConnection(pika.ConnectionParameters(
host='localhost'))
channel = connection.channel()
channel.queue_declare(queue='hound')
def callback(ch, method, properties, body):
print(" [x] Received %r" % (body,))
time.sleep(5)
print(" [x] Done")
ch.basic_ack(delivery_tag = method.delivery_tag)
channel.basic_consume(callback,
queue='hound',
)
print(' [*] Waiting for messages. To exit press CTRL+C')
channel.start_consuming()
And C++ client which tries to send message:
#include <SimpleAmqpClient/SimpleAmqpClient.h>
using namespace AmqpClient;
int main(int argc, char *argv[])
{
Channel::ptr_t channel;
channel = Channel::Create("SERVER_HOST", SERVER_PORT,
"LOGIN", "PASS", "/");
BasicMessage::ptr_t msg = BasicMessage::Create("HELLO!!!");
channel->DeclareQueue("hound");
channel->BasicPublish("", "hound", msg, true);
}
But when I sent message I got error:
terminate called after throwing an instance of 'AmqpClient::PreconditionFailedException'
what(): channel error: 406: AMQP_QUEUE_DECLARE_METHOD caused: PRECONDITION_FAILED - parameters for queue 'hound' in vhost '/' not equivalent
Aborted
But! When i delete line: channel->DeclareQueue("hound"); successfully sent.
Sender writte in Python is working well:
#!/usr/bin/env python
import sys
import pika
credentials = pika.PlainCredentials(
username=username, password=password
)
connection = pika.BlockingConnection(
pika.ConnectionParameters(
host=host,
virtual_host=virtual_host,
credentials=credentials,
port=RABBIT_PORT
)
)
channel = connection.channel()
channel.queue_declare(queue='hound')
channel.basic_publish(exchange='',
routing_key='hound',
body='hello!')
print(" [x] Sent %r" % (message,))
What's wrong? Why c++ client show me this error?
This error is caused by the fact that you are attempting to re-declare a queue with different parameters.
As the documentation states, a queue declaration is intended to be an idempotent assertion - if the queue does not exist, it is created. If it does exist, but has different parameters, you get this error.
Declaration and Property Equivalence
Before a queue can be used it has to be declared. Declaring a queue
will cause it to be created if it does not already exist. The
declaration will have no effect if the queue does already exist and
its attributes are the same as those in the declaration. When the
existing queue attributes are not the same as those in the declaration
a channel-level exception with code 406 (PRECONDITION_FAILED) will be
raised.
Something is going on in your DeclareQueue("hound"); method that is different from channel.queue_declare(queue='hound'). Since we don't have the code for that, it is impossible to explain further, but I think this is sufficient information for you to solve the problem.

how to store rabbitMQ messages

I am using a RabbitMQ server with python for sending and receiving messages to the server
This is the code I am using for sending a message in to code.
import numpy as np
import pandas as pd
import pika
connection = pika.BlockingConnection(pika.ConnectionParameters(
host='localhost'))
channel = connection.channel()
channel.queue_declare(queue='Q1')
message = 'Hello World'
channel.basic_publish(exchange='',
routing_key='Q1',
body=message)
# Printing the Sending Confirmation of ID
print(" [x] Sent %r" % message)
connection.close()
Output:
[x] Sent 'Hello World'
This is the code I am using for receiving messages from queue
import pika
import sys
connection = pika.BlockingConnection(pika.ConnectionParameters(host='localhost'))
channel = connection.channel()
channel.queue_declare(queue='Q1')
def callback(ch, method, properties, body):
print(" [x] Received %r" % body)
channel.basic_consume(callback, queue='Q1', no_ack=True)
channel.start_consuming()
Output:
[x] Received 'Hello World'
The problem is I want to save this message i.e. "Hello World" to a variable and then use it in my program
But I am not able to save the message.
How can I save it to a variable.
What will be the solution for Multiple Messages in the queue
The problem is I want to save this message i.e. "Hello World" to a variable and then use it in my program
You've got a variable already which you can use in you program - body. If you'd like to decouple the infrastructure code (i.e. RabbitMq/pika) from the business logic then you can simply declare another function and pass the body to it.
def processing_function(message_received):
print(" [x] Received %r" % message_received)
def callback(ch, method, properties, body):
processing_function(body)
The idea is that pika calls callback once a message is received and then body is passed to the processing_function which performs calculations.
If you're struggling to understand the callback function I'd recommend you to read this first.

rabbitmq messages missing in receiver part

I have implemented RabbitMQ in my servers. So basically what it does is that the main server passes messages to the worker server.
The problem that I am facing is that all the message that I pass is not received by the server.
i.e if i send 10 messages only 4 of them are received.
Any idea where am I going wrong.
Receiving code
import pika
connection = pika.BlockingConnection(pika.ConnectionParameters(
host='localhost'))
channel = connection.channel()
channel.queue_declare(queue='hello')
def callback(ch, method, properties, body):
print(" [x] Received %r" % body)
channel.basic_consume(callback,
queue='hello',
no_ack=True)
print(' [*] Waiting for messages. To exit press CTRL+C')
channel.start_consuming()
Publishing code
import pika
import sys
connection = pika.BlockingConnection(pika.ConnectionParameters(
host='localhost'))
channel = connection.channel()
channel.queue_declare(queue='task_queue', durable=True)
message = ' '.join(sys.argv[1:]) or "Hello World!"
channel.basic_publish(exchange='',
routing_key='task_queue',
body=message,
properties=pika.BasicProperties(
delivery_mode = 2, # make message persistent
))
print(" [x] Sent %r" % message)
connection.close()
Assuming that you are publishing to the same queue (as the examples you posted shows otherwise). I would recommend that you enable the confirm delivery flag. This will ensure that your message gets delivered, and if not it will either throw an exception, or publish will return False.
channel = connection.channel()
channel.confirm_delivery()
published = channel.basic_publish(...)
if not published:
raise Exception("Unable to publish message!")
It might also be worth to install the management plugin for RabbitMQ and inspect the queue before you start consuming messages. This way you can verify that the messages got published, and later consumed.

Categories

Resources