Now let's try working with Redis from Python. First, make sure to install the redis-py driver:
pip install redis
It is also recommended to install Hiredis along with redis-py. Hiredis is a parsing class written by the core Redis team, and redis-py will use Hiredis if it is present. Its use can provide a significant performance gain over the default PythonParser. The hiredis parser can be installed similarly via pip:
pip install hiredis
Let's write a simple script to set, get, and output a simple welcome message. Create a new Python script and call it redisHelloWorld.py.
First, we will add our imports. We will need StrictRedis, as well as the sys module to pull in command-line arguments:
from redis import StrictRedis import sys
Now we will pull in our hostname and password from the command-line arguments:
hostname = sys.argv[1] password = sys.argv[2]
Next, we will pass along the hostname and password to a local object to hold our StrictRedis connection data. Since the port won't be changing much, we'll hardcode that to be the default port of 6379. Additionally, we'll make sure we're sticking to database 0 (zero) by hardcoding that as well. But both port and db could very well be converted to command-line parameters as well:
r = StrictRedis(host=hostname,port=6379,password=password,db=0)
Here we will create a method to set the key packt:welcome to our message of Hello world from Python!:
def setPacktWelcome():
#SET new value packt:welcome
print("Writing \"Hello world from Python!\" to Redis...")
r.set('packt:welcome','Hello world from Python!')
Next, we will create a method to query that message and print it as output:
def getPacktWelcome():
#GET value stored in packt:welcome
print("Displaying current welcome message...")
value = r.get('packt:welcome')
print("message = " + str(value))
Finally, we will call the get, set, and then get once more. In this way, we are querying the packt:welcome key for its value, setting it to a new value, and then querying it again and posting the value as output:
getPacktWelcome() setPacktWelcome() getPacktWelcome()
Running this from the command line yields the following output:
python redisHelloWorld.py 127.0.0.1 currentHorseBatteryStaple Displaying current welcome message... message = Hello world! Writing "Hello world from Python!" to Redis... Displaying current welcome message... message = Hello world from Python!
As you can see, querying the key packt:welcome shows our initial value that we set in the redis-cli example. Next, we're setting the value to Hello world from Python! Finally, we query the same key and see our new message.
Now we'll try something a little different. Let's write a script to manage our entries into the packt:logins list that we have created, and keep the list to a size of three. We'll call this script redisQueryUser.py.
Our imports will be similar to the previous script, except that we'll include the datetime.datetime item:
from redis import StrictRedis from datetime import datetime import sys
In addition to passing the hostname and password for our Redis instance, we will also pass the userid and ip address. Additionally, we will connect to Redis the same way that we did in the previous script:
hostname=sys.argv[1] password=sys.argv[2] userid=sys.argv[3] ip=sys.argv[4] r = StrictRedis(host=hostname,port=6379,password=password,db=0)
Next, we will create a new method to log entries for the userid and ip address. This method will also log the current time, concatenate them all into a string, and execute a lpush onto the packt:logins list structure:
def addNewLogin(user,ipaddress):
print("Logging entry for " + user + " from " + ipaddress)
time = str(datetime.now())
r.lpush('packt:logins',user + " " + ipaddress + " " + time)
For the final command of that method, I'll execute a ltrim on the list. We only want to keep track of the last three user logins into our system. So, trimming the list (again from the left) from items zero to two ensures that there will only ever be three items in the list and that they will always be the three most recent entries:
r.ltrim('packt:logins',0,2)
Next, we'll write a simple method to query the complete list, and output it to the screen:
def getList():
list = r.lrange('packt:logins',0,-1)
print(list)
Finally, we will call both methods. This will add a new entry to the list, and query the list output:
addNewLogin(userid,ip) getList()
Running the script yields this output:
python redisQueryUser.py 127.0.0.1 currentHorseBatteryStaple aploetz 10.0.0.6 Logging entry for aploetz from 10.0.0.6 ['aploetz 10.0.0.6 2017-06-24 16:43:29.228135', 'aploetz 10.0.0.4 2017-06-24 16:31:58.171875', 'aploetz 10.0.0.4 2017-06-24 16:22:04.144998']
After running the script one more time, I can query it from within redis-cli to see its current contents:
127.0.0.1:6379> lrange packt:logins 0 -1 1) "aploetz 10.0.0.9 2017-06-24 16:43:49.958260" 2) "aploetz 10.0.0.6 2017-06-24 16:43:29.228135" 3) "aploetz 10.0.0.4 2017-06-24 16:31:58.171875"
As you can see, of the original two entries (done from the command line), only one remains. This affirms that our code to keep the list to a size of three is working correctly.
Next, let's write two scripts to demonstrate the Publish/Subscribe functionality of Redis. Let's assume that we are building a messaging application for baseball games. We'll start by creating our script (named redisPub.py) with our normal imports and argument processing statements:
#!/usr/bin/python
from redis import StrictRedis
import sys
if len(sys.argv) < 4:
print "Please enter a valid hostname, password, and channel."
exit(len(sys.argv))
hostname=sys.argv[1]
password=sys.argv[2]
channel=sys.argv[3]
Next, we'll set up our connection to Redis, and instantiate a local object named publisher to manage our message publishing:
r = StrictRedis(host=hostname,port=6379,password=password,db=0) publisher = r.pubsub()
With that complete, let's build a while loop to show a prompt, process our input, and publish the messages:
while True:
message=raw_input("Describe play, or press [Enter] to quit: ")
if not message:
break
else:
r.publish(channel,message)
print "Publish program ended."
Now let's shift gears to our subscriber script. We will name it redisSub.py. It will start with the same imports and argument processing statements as the previous script did:
#!/usr/bin/python
from redis import StrictRedis
import sys
if len(sys.argv) < 4:
print "Please enter a valid hostname, password, and channel."
exit(len(sys.argv))
hostname=sys.argv[1]
password=sys.argv[2]
channel=sys.argv[3]
Next, we'll set up our connection to Redis, and instantiate a local object for our channels. Additionally, we'll issue a command to subscribe to the provided channel:
r = StrictRedis(host=hostname,port=6379,password=password,db=0) channels = r.pubsub() channels.subscribe(channel)
With that complete, we can now build a for loop to listen for messages. We will use an if construct to see if the message consists of the uppercase word END. If it does, we'll break from the loop. Otherwise, we will print the message contents:
for message in channels.listen():
if message['data']=='END': break else: print message['data']
channels.unsubscribe(channel)
print "Unsubscribed"
Now let's see these scripts in action! As with our redis-cli Publish/Subscribe example, we'll need to open two terminal windows: one for the subscriber and one for the publisher. Starting with the subscriber, let's invoke it with our localhost (127.0.0.1), our password, and OMG15UBaseball as our channel:
python redisSub.py 127.0.0.1 currentHorseBatteryStaple OMG15UBaseball 1
After running that command, Redis returns a 1 as our first message, indicating that we are listening on a single channel. Next, let's run the publisher in another terminal window:
python redisPub.py 127.0.0.1 currentHorseBatteryStaple OMG15UBaseball Describe play; [Enter] to quit: Henry strikes out swinging (Out 1). Describe play; [Enter] to quit: Avery singles to RF. Describe play; [Enter] to quit: Avery steals 2b. Describe play; [Enter] to quit: Gareth doubles to LF, Avery scores. Describe play; [Enter] to quit: Gareth steals 3b. Describe play; [Enter] to quit: Leighton grounds out to SS, Gareth scores (Out 2). Describe play; [Enter] to quit: Aaron grounds out to SS (Out 3). Describe play; [Enter] to quit: END Describe play; [Enter] to quit: Publish program ended.
When we look at the terminal running our subscriber, the following output is displayed:
1 Henry strikes out swinging (Out 1). Avery singles to RF. Avery steals 2b. Gareth doubles to LF, Avery scores. Gareth steals 3b. Leighton grounds out to SS, Gareth scores (Out 2). Aaron grounds out to SS (Out 3). Unsubscribed