• Stars
    star
    290
  • Rank 142,981 (Top 3 %)
  • Language
    Python
  • License
    BSD 2-Clause "Sim...
  • Created about 11 years ago
  • Updated 8 months ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Rich Python data types for Redis

image

Created by Stephen McDonald

Introduction

HOT Redis is a wrapper library for the redis-py client. Rather than calling the Redis commands directly from a client library, HOT Redis provides a wide range of data types that mimic many of the built-in data types provided by Python, such as lists, dicts, sets, and more, as well as many of the classes found throughout the standard library, such as those found in the Queue, threading, and collections modules.

These types are then backed by Redis, allowing objects to be manipulated atomically over the network - the atomic nature of the methods implemented on objects in HOT Redis is one of its core features, and many of these are backed by Lua code executed within Redis, which ensures atomic operations where applicable.

The name HOT Redis originally stood for "Higher Order Types for Redis", but since the implementation doesn't strictly fit the definition, the recursive acronym "HOT Object Toolkit for Redis" should appease the most luscious of bearded necks.

HOT Redis was drawn from the infrastructure behind the Kouio RSS reader, a popular alternative to Google Reader.

Installation

The easiest way to install hot-redis is directly from PyPi using pip by running the following command:

$ pip install -U hot-redis

Otherwise you can download and install it directly from source:

$ python setup.py install

Usage

Each of the types provided by HOT Redis strive to implement the same method signatures and return values as their Python built-in and standard library counterparts. The main difference is each type's __init__ method. Every HOT Redis type's __init__ method will optionally accept initial and key keyword arguments, which are used for defining an initial value to be stored in Redis for the object, and the key that should be used, respectively. If no key is provided, a key will be generated, which can then be accessed via the key attribute:

>>> from hot_redis import List
>>> my_list = List()
>>> my_list.key
'93366bdb-90b2-4226-a52a-556f678af40e'
>>> my_list_with_key = List(key="foo")
>>> my_list_with_key.key
'foo'

Once you've determined a strategy for naming keys, you can then create HOT Redis objects and interact with them over the network, for example here is a List created on a computer we'll refer to as computer A:

>>> list_on_computer_a = List(key="foo", initial=["a", "b", "c"])

then on another computer we'll creatively refer to as computer B:

>>> list_on_computer_b = List(key="foo")
>>> list_on_computer_b[:]  # Performs: LRANGE foo 0 -1
['a', 'b', 'c']
>>> list_on_computer_b += ['d', 'e', 'f']  # Performs: RPUSH foo d e f

and back to computer A:

>>> list_on_computer_a[:]  # Performs: LRANGE foo 0 -1
['a', 'b', 'c', 'd', 'e', 'f']
>>> 'c' in list_on_computer_a  # Works like Python lists where expected
True
>>> list_on_computer_a.reverse()
>>> list_on_computer_a[:]
['f', 'e', 'd', 'c', 'b', 'a']

The last interaction here is an interesting one. Python's list.reverse() is an in-place reversal of the list, that is, it modifies the existing list, rather than returning a reversed copy. If we were to implement this naively, we would first read the list from Redis, reverse it locally, then store the reversed list back in Redis again. But what if another client were to modify the list at approximately the same time? One computer's modification to the list would certainly overwrite the other's. In this scenario, and many others, HOT Redis provides its own Lua routine specifically for reversing the list in-place, within Redis atomically. I wrote in more detail about this in a blog post, Bitwise Lua Operations in Redis.

Configuration

By default, HOT Redis attempts to connect to a Redis instance running locally on the default port 6379. You can configure the default client by calling the hot_redis.configure function, prior to instantiating any HOT Redis objects. The arguments given to configure are passed onto the underlying redis-py client:

>>> from hot_redis import configure
configure(host='myremotehost', port=6380)

Alternatively, if you wish to use a different client per object, you can explicitly create a HotClient instance, and pass it to each object:

>>> from hot_redis import HotClient, Queue
>>> client = HotClient(host="myremotehost", port=6380)
>>> my_queue = Queue(client=client)

Transactions

Basic support for thread-safe transactions are provided using the Redis MULTI and EXEC commands:

>>> from hot_redis import List, Queue, transaction
>>> my_list = List(key="foo")
>>> my_queue = Queue(key="bar")
>>> with transaction():
...     for i in range(20):
...         my_list.append(i)
...         my_queue.put(i)

In the above example, all of the append and put calls are batched together into a single transaction, that is executed once the transaction() context is exited.

Data Types

The following table is the complete list of types provided by HOT Redis, mapped to their Python counterparts and underlying Redis types, along with any special considerations worth noting.

HOT Redis Python Redis Notes

List Set Dict

list set dict

list set hash

String string string Mutable - string methods that normally create a new string object in Python will mutate the string stored in Redis

ImmutableString Int Float Queue LifoQueue

string int float Queue.Queue Queue.LifoQueue

string int float list list

Immutable - behaves like a regular Python string

SetQueue N/A list + set Extension of Queue with unique members
LifoSetQueue N/A list + set Extension of LifoQueue with unique members
BoundedSemaphore threading.BoundedSemaphore list Extension of Queue leveraging Redis' blocking list pop operations with timeouts, while using Queue's maxsize arg to provide BoundedSemaphore's value arg
Semaphore threading.Semaphore list Extension of BoundedSemaphore without a queue size
Lock threading.Lock list Extension of BoundedSemaphore with a queue size of 1

RLock DefaultDict MultiSet

threading.RLock collections.DefaultDict collections.Counter

list hash hash

Extension of Lock allowing multiple acquire calls

More Repositories

1

mezzanine

CMS framework for Django
Python
4,757
star
2

django-socketio

WebSockets for Django
Python
1,318
star
3

cartridge

Ecommerce for Mezzanine
Python
708
star
4

django-forms-builder

Let users build forms in Django admin
Python
689
star
5

curiodb

Distributed NoSQL Database
Scala
511
star
6

drum

Reddit / Hacker News clone for Mezzanine
Python
387
star
7

gnotty

IRC web client and bot framework
Python
159
star
8

django-overextends

Circular template inheritance for Django
Python
108
star
9

two-queues

Benchmarking Redis and ZeroMQ pub-sub, using Python and Go
Go
105
star
10

gunicorn-console

A curses application for managing gunicorn processes.
Python
90
star
11

django-postgres-fuzzycount

Fast / fuzzy PostgreSQL counts for Django
Python
89
star
12

django-email-extras

PGP encrypted / multipart templated emails for Django
Python
75
star
13

filebrowser-safe

File manager for Mezzanine
Python
41
star
14

hg-github

A Mercurial extension for working with GitHub repositories.
Python
40
star
15

vimeo-deck

Synchronize Speaker Deck presentations with Vimeo videos.
JavaScript
28
star
16

gamblor

An online casino app built for Django Dash 2012
JavaScript
26
star
17

grappelli-safe

Admin skin for Mezzanine
CSS
25
star
18

snazzymaps-browser

Android app for searching and browsing Snazzy Maps
Java
24
star
19

grillode

A web-based chat application written in CoffeeScript for Node.js
CoffeeScript
23
star
20

drawnby

Drawn By is a collaborative real-time sketching app built for the 2011 Django Dash.
JavaScript
23
star
21

babbler

A Twitter bot that polls an RSS feed and posts its entries as tweets, with auto-generated hashtags.
Python
21
star
22

tastypie-msgpack

MsgPack support for Django Tastypie.
Python
21
star
23

django-shotgun

Test entire Django sites
Python
17
star
24

linkedout

Build PDF resumes with the LinkedIn API
Ruby
15
star
25

sphinx-me

Wraps your README-only projects in a dynamic Sphinx shell for hosting on http://readthedocs.org
Python
12
star
26

readertray

Cross platform desktop notifications for RSS
Python
9
star
27

indexed-tree-map

JDK's enhanced red-black tree map algorithm to support access by index
Java
9
star
28

otr

Combined GitHub and Bitbucket API.
Ruby
8
star
29

aspchat

Classic ASP chat application
ASP
8
star
30

bitbucket-batch

A tool for bulk updating access to bitbucket.org repos.
Python
8
star
31

grillo

A terminal based chat server and client.
Python
7
star
32

mezzanine.jupo.org

Mezzanine/Cartridge project and demo site
Python
6
star
33

ratemyflight

A web app built for the Django Dash hackathon 2010.
JavaScript
6
star
34

klout-feed

Receive your daily Klout score via RSS.
Ruby
6
star
35

slbuddy

Tool for tracking sales data in Secondlife.com
Python
3
star
36

virtualboxing

Utilities for comparing timings on bulk operations across databases in a distributed environment.
Ruby
3
star
37

cryptopals

Matasano Crypto Challenges
Go
3
star
38

ghetto-life-stream

Parses items for a Google Buzz feed from various sources.
PHP
2
star
39

teamcity-client

Team City HTTP client.
Ruby
2
star
40

sydjango-damm

Code for my SyDjango talk "Django Admin: The Missing Manual"
Python
2
star
41

jquery-squeezebox

Replacement for jquery.ui.accordion to avoid dealing with jquery.ui theming.
JavaScript
2
star
42

lime

JavaScript framework, predates jQuery
JavaScript
1
star
43

cmdsvr

Toy web application server
Python
1
star
44

gedit-ftp-browser

FTP plugin for Gedit
Python
1
star