Git Product home page Git Product logo

redis-py's Introduction

redis-py

The Python interface to the Redis key-value store.

CI docs MIT licensed pypi pre-release codecov

Installation | Usage | Advanced Topics | Contributing


**Note: ** redis-py 5.0 will be the last version of redis-py to support Python 3.7, as it has reached end of life. redis-py 5.1 will support Python 3.8+.


How do I Redis?

Learn for free at Redis University

Try the Redis Cloud

Dive in developer tutorials

Join the Redis community

Work at Redis

Installation

Start a redis via docker:

docker run -p 6379:6379 -it redis/redis-stack:latest

To install redis-py, simply:

$ pip install redis

For faster performance, install redis with hiredis support, this provides a compiled response parser, and for most cases requires zero code changes. By default, if hiredis >= 1.0 is available, redis-py will attempt to use it for response parsing.

$ pip install "redis[hiredis]"

Looking for a high-level library to handle object mapping? See redis-om-python!

Supported Redis Versions

The most recent version of this library supports redis version 5.0, 6.0, 6.2, 7.0 and 7.2.

The table below highlights version compatibility of the most-recent library versions and redis versions.

Library version Supported redis versions
3.5.3 <= 6.2 Family of releases
>= 4.5.0 Version 5.0 to 7.0
>= 5.0.0 Version 5.0 to current

Usage

Basic Example

>>> import redis
>>> r = redis.Redis(host='localhost', port=6379, db=0)
>>> r.set('foo', 'bar')
True
>>> r.get('foo')
b'bar'

The above code connects to localhost on port 6379, sets a value in Redis, and retrieves it. All responses are returned as bytes in Python, to receive decoded strings, set decode_responses=True. For this, and more connection options, see these examples.

RESP3 Support

To enable support for RESP3, ensure you have at least version 5.0 of the client, and change your connection object to include protocol=3

>>> import redis
>>> r = redis.Redis(host='localhost', port=6379, db=0, protocol=3)

Connection Pools

By default, redis-py uses a connection pool to manage connections. Each instance of a Redis class receives its own connection pool. You can however define your own redis.ConnectionPool.

>>> pool = redis.ConnectionPool(host='localhost', port=6379, db=0)
>>> r = redis.Redis(connection_pool=pool)

Alternatively, you might want to look at Async connections, or Cluster connections, or even Async Cluster connections.

Redis Commands

There is built-in support for all of the out-of-the-box Redis commands. They are exposed using the raw Redis command names (HSET, HGETALL, etc.) except where a word (i.e. del) is reserved by the language. The complete set of commands can be found here, or the documentation.

Advanced Topics

The official Redis command documentation does a great job of explaining each command in detail. redis-py attempts to adhere to the official command syntax. There are a few exceptions:

  • MULTI/EXEC: These are implemented as part of the Pipeline class. The pipeline is wrapped with the MULTI and EXEC statements by default when it is executed, which can be disabled by specifying transaction=False. See more about Pipelines below.

  • SUBSCRIBE/LISTEN: Similar to pipelines, PubSub is implemented as a separate class as it places the underlying connection in a state where it can't execute non-pubsub commands. Calling the pubsub method from the Redis client will return a PubSub instance where you can subscribe to channels and listen for messages. You can only call PUBLISH from the Redis client (see this comment on issue #151 for details).

For more details, please see the documentation on advanced topics page.

Pipelines

The following is a basic example of a Redis pipeline, a method to optimize round-trip calls, by batching Redis commands, and receiving their results as a list.

>>> pipe = r.pipeline()
>>> pipe.set('foo', 5)
>>> pipe.set('bar', 18.5)
>>> pipe.set('blee', "hello world!")
>>> pipe.execute()
[True, True, True]

PubSub

The following example shows how to utilize Redis Pub/Sub to subscribe to specific channels.

>>> r = redis.Redis(...)
>>> p = r.pubsub()
>>> p.subscribe('my-first-channel', 'my-second-channel', ...)
>>> p.get_message()
{'pattern': None, 'type': 'subscribe', 'channel': b'my-second-channel', 'data': 1}

Author

redis-py is developed and maintained by Redis Inc. It can be found here, or downloaded from pypi.

Special thanks to:

  • Andy McCurdy ([email protected]) the original author of redis-py.
  • Ludovico Magnocavallo, author of the original Python Redis client, from which some of the socket code is still used.
  • Alexander Solovyov for ideas on the generic response callback system.
  • Paul Hubbard for initial packaging support.

Redis

redis-py's People

Contributors

akx avatar andrew-chen-wang avatar andymccurdy avatar angusp avatar avitalfineredis avatar barshaul avatar chayim avatar chillipino avatar dcolish avatar dependabot[bot] avatar dogukanteber avatar dvora-h avatar dwilliams-kenzan avatar enjoy-binbin avatar gerzse avatar gkorland avatar hydrogen18 avatar itamarhaber avatar jdufresne avatar kmerenkov avatar krishan-carbon avatar kristjanvalur avatar shacharpash avatar theodesp avatar thruflo avatar tilgovi avatar uglide avatar utkarshgupta137 avatar vitek avatar wolever avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

redis-py's Issues

Redis.select() requires host and port

From the documentation for the select method of Redis:

Switch to a different database on the current host/port

However, host and port are required parameters:

def select(self, host, port, db, password=None, socket_timeout=None):

Can we make host and port optional, with db the only required parameter?

BUG: redis-py 1.3.4 with a redis-1.3.4 server - keys response parsed incorrectly

It looks like the protocol response from the server has changed slightly for the keys function (and possibly others untested). Where our old servers (1.2.1) used to say this;

KEYS *
$3
foo

... the new server (1.3.4) says this;

KEYS *
*1
$3
foo

I think it is preceding the #bytes with the #responses, in this case 1. What this means for the lambda called from RESPONSE_CALLBACKS for keys, is that it gets a list and attempts to split it (because it is expecting a string)

'KEYS' : lambda r: r and r.split(' ') or [],

To see it in action, start up a 1.3.4 server (got mine from github), crank up a python interpreter, and fire away;

r.info()
{'bgrewriteaof_in_progress': 0, 'uptime_in_days': 0, 'multiplexing_api': 'epoll', 'last_save_time': 1268698696, 'redis_version': '1.3.4', 'connected_clients': 1, 'hash_max_zipmap_value': 512, 'vm_enabled': 0, 'role': 'master', 'total_commands_processed': 30, 'total_connections_received': 9, 'used_memory_human': '523.43K', 'blocked_clients': 0, 'process_id': 19110, 'connected_slaves': 0, 'db0': {'keys': 1, 'expires': 0}, 'arch_bits': 64, 'hash_max_zipmap_entries': 64, 'bgsave_in_progress': 0, 'used_memory': 535993, 'uptime_in_seconds': 4054, 'changes_since_last_save': 1}

r.keys('*')
[]

r.set('foo', 'zoo')
True

r.keys('*')
Traceback (most recent call last):
File "", line 1, in
File "build/bdist.linux-x86_64/egg/redis/client.py", line 440, in keys
File "build/bdist.linux-x86_64/egg/redis/client.py", line 284, in format_inline
File "build/bdist.linux-x86_64/egg/redis/client.py", line 220, in execute_command
File "build/bdist.linux-x86_64/egg/redis/client.py", line 215, in _execute_command
File "build/bdist.linux-x86_64/egg/redis/client.py", line 269, in parse_response
File "build/bdist.linux-x86_64/egg/redis/client.py", line 181, in
AttributeError: 'list' object has no attribute 'split'

I'm in the process of porting some code from 0.6.3(?) because you now have pipelining (yay), but this is a bit of a bu99er because I use the keys call a lot. It is possible that other calls I haven't come across could be affected by this variation in protocol response.

Cheers
Sam

pipeline and transactions should not be the same

Since your commit bd411f9 redis-py executes pipelines atomically with MULTI/EXEC commands.
But pipelines and transactions are not the same, redis can handle a pipeline without MULTI/EXEC as before, and sometines it's what we want. After a long talk with Salvatore/Antirez, the two ways should be provided (transactions use more memory and are a bit slower).
Maybe an option to the pipeline command ?

Redis.smove does not encode value

All other operations pass the value through the _encode method to convert ints, floats, and unicode into the proper string object with appropriate charset. smove does not do this, and passes the value (named member) directly into the command. This results in an AttributeError if the member being passed in is not a string type. Further errors may also occur if the type is a unicode with unsupported characters, or is a list/set/dict.

e.g.:
r = redis.Redis()
r.smove('set', 'list', 3)
Traceback (most recent call last):
File "", line 1, in
File "redis.py", line 808, in smove
src, dst, len(member), member
TypeError: object of type 'int' has no len()

Pipeline case does a lot of socket 'sendto' system calls

Hi,

In the pipeline use-case it might be benificial to build up a string containing a number of commands and write them out in 1 call to socket.sendall. This will most probably result in better bandwidth usage for the socket connection and thus higher overall number of commands/sec.

pairs_to_dict forces float cast for values

Heya Andy, thanks for the speedy turnaround on the new hash functions. I notice however that the pairs_to_dict function is forcing values to be cast as float via a map call. Is this intended? It means I can't put string values into a hash.

r.hset('foo', 'bar', 'zoo')
1
r.hgetall('foo')
Traceback (most recent call last):
File "", line 1, in
File "redis/client.py", line 902, in hgetall
File "redis/client.py", line 325, in format_inline
File "redis/client.py", line 247, in execute_command
File "redis/client.py", line 242, in _execute_command
File "redis/client.py", line 310, in parse_response
File "redis/client.py", line 207, in
File "redis/client.py", line 158, in pairs_to_dict
ValueError: invalid literal for float(): zoo

Not sure what side effect there would be from removing the float call - other than everything coming back as a string. Maybe instead of mapping to float, it could use a function like this?

def map_type(value):
... try:
... return '.' in value and float(value) or int(value)
... except ValueError:
... return value

Anyway, thought I would let you know =]

Cheers
Sam

sort start/num check is broken

0 is False in Python, so passing start=0, num=20 to sort will return all the results.

Line 676:
if start and num
Should be:
if start != None and num != None:

Connection pooling can be messed up by select()

The following sequence of commands poses a problem for redis-py. It is a reduction of a real sequence of commands invoked by a copy script I wrote, and needless to say, figuring out the behavior in the comments confused me mightily.

 from redis import Redis
 source = Redis(db=0) # source opens a new connection to localhost/0
 dest = Redis(db=0)   # dest uses the existing connection to localhost/0
 source.select(1)     # since source and dest are sharing a connection,
                      # they will now both operate on database 1

 copy(source, dest)   # doesn't accomplish anything useful!

AUTH doesn't work

I'm using something like this:

    self.redis = Redis(host=options.redis_host, port=options.redis_port, db=options.redis_db)
    self.redis.auth('fooword')

And I get this output:

[frank@isamu 61924]$ python index.py 
Traceback (most recent call last):
  File "index.py", line 651, in <module>
    main()
  File "index.py", line 644, in main
    http_server = tornado.httpserver.HTTPServer(Application())
  File "index.py", line 126, in __init__
    self.redis.auth('fooword')
  File "/srv/http/nginx/61924/modules/redis.py", line 1261, in auth
    return self.send_command('AUTH %s\r\n' % passwd)
  File "/srv/http/nginx/61924/modules/redis.py", line 122, in _send_command_retry
    return self._send_command(s)
  File "/srv/http/nginx/61924/modules/redis.py", line 110, in _send_command
    self.connect()
  File "/srv/http/nginx/61924/modules/redis.py", line 1355, in connect
    self.select(self.db)
  File "/srv/http/nginx/61924/modules/redis.py", line 1164, in select
    return self.send_command('SELECT %s\r\n' % db)
  File "/srv/http/nginx/61924/modules/redis.py", line 122, in _send_command_retry
    return self._send_command(s)
  File "/srv/http/nginx/61924/modules/redis.py", line 118, in _send_command
    return self._get_response()
  File "/srv/http/nginx/61924/modules/redis.py", line 1273, in _get_response
    raise ResponseError(err)
modules.redis.ResponseError: operation not permitted

When I use telnet it works:

[frank@isamu 61924]$ telnet localhost 6379
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
AUTH fooword
+OK

Feature request: support for multiple parameters to delete()

The DEL supports multiple parameters, can redis-py also support this?

I expect it could be done as follows:

def delete(self, *args):
    """
    >>> r = Redis(db=9)
    >>> r.delete('dsjhfksjdhfkdsjfh')
    0
    >>> r.set('a', 'a')
    'OK'
    >>> r.delete('a')
    1
    >>> r.exists('a')
    0
    >>> r.delete('a')
    0
    >>> 
    """
    return self.send_command('DEL %s\r\n' % " ".join(args))

Thank you!

zscore throws exception for missing member

Redis documentation states that for missing members of zset it returns (nil). It's naturally to expect None on python's side.

Steps to reproduce:
r=Redis()
r.zadd('test', 'foo', 0)
r.zscore('test', 'bar')

hmset with 0 length array fails

it probably should just do a noop. Here's the stack trace

  File "/Users/mike/Documents/Scribd/iseo/sessions/ression.py", line 28, in pipe
    self.p.execute() # execute the remaining commands
  File "build/bdist.macosx-10.6-x86_64/egg/redis/client.py", line 1310, in execute
    return execute(stack)
  File "build/bdist.macosx-10.6-x86_64/egg/redis/client.py", line 1275, in _execute_transaction
    _ = self.parse_response('_')
  File "build/bdist.macosx-10.6-x86_64/egg/redis/client.py", line 390, in parse_response
    response = self._parse_response(command_name, catch_errors)
  File "build/bdist.macosx-10.6-x86_64/egg/redis/client.py", line 349, in _parse_response
    raise ResponseError(response)
ResponseError: wrong number of arguments for 'hmset' command

BLPOP and BRPOP return no values

I'm running redis-py f4c8393 with Redis 1.3.10. I can't get BLPOP and BRPOP to work correctly from Python:

$ python
Python 2.6.5 (r265:79063, Apr  3 2010, 01:57:29) 
[GCC 4.4.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import redis
>>> r = redis.Redis()
>>> r.rpush('mylist', 'a')
1
>>> r.rpush('mylist', 'b')
2
>>> r.rpush('mylist', 'c')
3
>>> r.blpop('mylist', 1)
>>> r.blpop('mylist', 1)
>>> r.blpop('mylist', 1)
>>> r.brpop('mylist', 1)
>>> r.brpop('mylist', 1)
>>> r.brpop('mylist', 1)

While the same works correctly in the Redis shell:

$ redis-cli
redis> rpush mylist a
(integer) 1
redis> rpush mylist b
(integer) 2
redis> rpush mylist c
(integer) 3
redis> blpop mylist 1
1. mylist
2. a
redis> brpop mylist 1
1. mylist
2. c
redis> brpop mylist 1
1. mylist
2. b
redis> brpop mylist 1
(nil)

Feature request: Namespace support

Proposal:

r = redis.Redis(namespace='foobar')

Behind-the-scenes, this would prefix every key with foobar.

For example, if I issued the following command:

r.set('abc', 'xyz')

It would be equivalent to the following:

redis-cli set foobar:abc xyz

In Ruby, the redis-namespace class does the same thing.

However, I think that it would be preferable if this were a core feature of the Python client.

r.keys() from redis-py v1.34.1 failing against redis 2.0.0-rc1

See here for original submission; http://code.google.com/p/redis/issues/detail?id=260

Running the client against this DB produces;

Traceback (most recent call last):
File "", line 1, in
File "build/bdist.macosx-10.5-i386/egg/redis/client.py", line 440, in keys
File "build/bdist.macosx-10.5-i386/egg/redis/client.py", line 284, in format_inline
File "build/bdist.macosx-10.5-i386/egg/redis/client.py", line 220, in execute_command
File "build/bdist.macosx-10.5-i386/egg/redis/client.py", line 215, in _execute_command
File "build/bdist.macosx-10.5-i386/egg/redis/client.py", line 269, in parse_response
File "build/bdist.macosx-10.5-i386/egg/redis/client.py", line 181, in
AttributeError: 'list' object has no attribute 'split'

From:
import redis
r = redis.Redis()
r.keys('*')

message not retrieved with psubscribe

With psubscribe, the original message is the fourth parts of the response, not the third (the third is the original channel), but only the three firsts aretaken from the response.

You should add a condition in the listen method (and one day i shloud fork redis-py to make this and do some pull requests time to time... )

Type inference does not work with byte buffers

The following code (the last lines of _get_value) does not work properly if the value stored in Redis is a byte buffer.

data = ''.join(buf)[:-2]
try:
    if not '.' in data:
        value = int(data)
    else:
        value = self.float_fn(data)
    return value
except (ValueError, decimal.InvalidOperation):
    return data.decode(self.charset)

Ignoring the general type inference issues (discussed on the Redis mailing list here: http://groups.google.com/group/redis-db/browse_thread/thread/9888eb9ff383c90c), there is a serious issue with the data.decode call in the event that the data is representative of a byte buffer. In this case, decoding the buffer with a codec results in an incorrect response being returned to the client. Instead, data itself should be returned to the caller.

potential bugs in _send_command and _read

I was browsing the driver source in the course of reviewing Redis for work and found a few potential bugs in the socket code.

The _read() method is calling "return self._fp.readline()", but this is bypassing the code at the end of the method which should be checking to see if self._sock.recv()=='', so a disconnect will likely not be handled correctly. It seems that _get_response() might handle this correctly, but _get_value() will raise a ValueError instead of a ConnectionError.

In the _send_command() method, if an EPIPE is raised, it won't work across platforms because it's checking if the value is 32, and not errno.EPIPE. I've had trouble with this in the past, as Linux and OSX use different enumerations.

RFE: Sharding

Would it be possible to implement automatic sharding similar to the redis Ruby library?

Multithreaded PubSub - Outside thread subscribes to new channel

I'm not quite sure if this is supposed to work but, it feels like it should. The use case demonstrated here:

  • a "listener" thread is used since the .listen() function is blocking
  • a separate thread tries to subscribe to a new channel
  • messages from the new channel should come through the "listener" thread but, don't
    import redis
    import threading
    from time import sleep
    
    

r = redis.Redis()

def listener():
r.subscribe("channel1")
for m in r.listen():
print m

def publisher():
while True:
sleep(1)
r.publish("channel1", "message")
r.publish("channel2", "message")

def wait_then_subscribe():
sleep(5)
r.subscribe("channel2")
print "subscribed to channel 2"

threading.Thread(target=listener).start()
threading.Thread(target=publisher).start()
threading.Thread(target=wait_then_subscribe).start()

Output:

$ python redis-thread-test.py 
{'data': 1, 'type': 'subscribe', 'channel': 'channel1'}
{'data': 'message', 'type': 'message', 'channel': 'channel1'}
{'data': 'message', 'type': 'message', 'channel': 'channel1'}
{'data': 'message', 'type': 'message', 'channel': 'channel1'}
{'data': 'message', 'type': 'message', 'channel': 'channel1'}
{'data': 'message', 'type': 'message', 'channel': 'channel1'}
subscribed to channel 2
{'data': 'message', 'type': 'message', 'channel': 'channel1'}
{'data': 'message', 'type': 'message', 'channel': 'channel1'}
{'data': 'message', 'type': 'message', 'channel': 'channel1'}

not work with pipeline if extend Redis

Pipeline extends Redis, If I want to write a subclass extends Redis ,add some new method just like set_obj,get_obj in my own serialization, the pipeline should not work with these method. Because it extends Redis not my subclass.

Should pipeline be a embedded executor ?

Any good ideas?

not work on multi threads

try the code below. you will found that the output is not what we want. what we want is like string of valuexxx. but there is many 1 and OK ... sometimes errors occurs.

from redis import Redis
import threading

r = Redis()

def t1():
    while True:
        r.set('key1', 'value1')

def t2():
    i = 1
    while True:
        i = i + 1
        r.sadd('key2', 'value%d' % i)

def t3():
    while True:
        print r.spop('key2')

threading.Thread(target=t1).start()
threading.Thread(target=t2).start()
threading.Thread(target=t3).start()

Redis.keys: AttributeError: 'int' object has no attribute 'split'

Python 2.6.1 (r261:67515, Jul  7 2009, 23:51:51) 
[GCC 4.2.1 (Apple Inc. build 5646)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> from redis import Redis, ConnectionError, ResponseError
>>> r = Redis(db=0)
>>> r.keys('*')
[]
>>> r.set(1, 'somevalue')
'OK'
>>> r.keys('*')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "build/bdist.macosx-10.6-universal/egg/redis.py", line 337, in keys
AttributeError: 'int' object has no attribute 'split'

retry_connection

i'm testing my code against the 1.34.1 version and noticed that the retry_connection keyword argument is no longer available. Is this an intentional ommission from the Redis class initialization?

More Pythonic to return empty list/set rather than None?

What steps will reproduce the problem?

  1. Execute a command which doesn't have any results.

What is the expected output? What do you see instead?
Expected to return an empty list/set, instead got None.

What version of the product are you using? On what operating system?
redis-1.34.1-py2.6

E.g.

for x in red.zrange('non_existent_key', 0, -1):
do_something()
Traceback (most recent call last):
File "", line 1, in
TypeError: 'NoneType' object is not iterable

zadd( 'test', 555, 'nan') crashes redis server

For some reason having a value that startswith('nan') crashes my redis server (1.2.2)

I'm not sure if this is a server or client issue, but I was unable to duplicate this crash using redis-cli so I'm leaning towards client.

Incorrect conversion of numeric return values

Currently all values will be converted using int or float_fn in _get_value if it's possible.
This is done regardless of what was actually put in.
This can lead to some hard to spot errors.

Example

v1 = "1234567" # E.g. hash values or something "non controllable"
v2 = "1ab3dc8"
type(v1), v1, type(v2), v2 => (<type 'str'>, '1234567', <type 'str'>, '1ab3dc8')

redis.Redis().set("a", v1)
redis.Redis().set("b", v2)

v1 = redis.Redis().get("a")
v2 = redis.Redis().get("b")
type(v1), v1, type(v2), v2 => (<type 'int'>, 1234567, <type 'unicode'>, u'1ab3dc8')

As you can see the returned values no longer match in type. It's not very intuitive that some values automatically gets converted while other doesn't.

I think it would be more appropriate to always return the non converted values, unless, if made possible, some other type where explicitly provided.

zrank throws TypeError for items not in a zset

sorry, i'm not an experienced issue reporter, hope the above code helps reproduce the problem.

In [48]: cache = Redis()
In [49]: cache.zadd("test", 'a', 1)
Out[49]: True
In [50]: cache.zadd("test", 'b', 2)
Out[50]: True
In [51]: cache.zrange("test", 0, 10)
Out[51]: ['a', 'b']
In [52]: cache.zrank("test", 'a')
Out[52]: 0
In [53]: cache.zrank("test", 'b')
Out[53]: 1
In [54]: cache.zrank("test", 'c')

TypeError Traceback (most recent call last)

[...]

TypeError: int() argument must be a string or a number, not 'NoneType'

Cannot do psubscribe after subscribe

When a subscribe command is done, i can't do a psubscribe.

I think you should add PSUBSCRIBE and PUNSUBSCRIBE in SUBSCRIPTION_COMMANDS line 245

Twidi

blpop / brpop; unexpected behavior if you pass a single string as the 'keys' arg

doesn't really decide if this a bug but i thought i should mention it.

if you pass a single string as the 'keys' arg to blpop or brpop it will become a list of chars of that string (because of the call of list(keys)) which is obviously not what you want.

i'd write something like this instead:

    [...]
    if isinstance(keys, basestring):
        keys = [keys]
    keys = list(keys)
    [...]

Python Client queues request when link down

What steps will reproduce the problem?

  1. r.set("test","testdata") #to make a real connection with the server
  2. ifdown eth0 # eth0 is the IF to the redis server
  3. r.set("test","testdata") #this one will not return for a long long time
  4. ifup eth0
  5. the r.set command in step #3 returns OK after serveral minutes.

What is the expected output? What do you see instead?

in step #3 above, the r.set should return immediately or throw an exception

What version of the product are you using? On what operating system?

Linux (Ubuntu 9.04)
Python Redis Client from GIT on May 29. 2010.
Redis 2.0.0 Rc1

client doesn't recover after invalid argument in Redis.set()

Following code does not work:

import redis.client
db = redis.client.Redis('localhost', 6379)
db.set("example","123")
True
try:
... db.set("invalid key","123")
... except Exception, e:
... print str(e)
...
wrong number of arguments for 'set' command
db.set("example","123")
Traceback (most recent call last):
...
File "<...>\redis\client.py", line 274, in _parse_response
raise ResponseError(response)
redis.exceptions.ResponseError: unknown command '123'

The same behavior is with Redis server 1.2.2 and 1.3.7

ConnectManager causes hour-long bug stalking in some cases :-)

ConnectManager causes hour-long bug stalking in some cases :-)

Scenario:
An application is doing something with redis, then it have to calculate something terribly big. In order to do it faster, it forks. Each fork creates new Redis() instance.
The problem is that connection is reused, and all forked processes share socket, and it causes magic bugs because you haven't asked for connection sharing but it's there! :)

Solve to problem:
Redis instance should accept keyword argument connection_pool=None.
And keep connection_manager inside itself instead on module-level.

I can write a fix in few minutes, but I want to clarify this:
Why share connections by default? I think that pool must be explicit rather than implicit.

UNSUBSCRIBE does not actually UNSUB consumer.

Issuing an UNSUBSCRIBE request does not actually cause an UNSUBSCRIBE on the latest Git repo version.

The following code generates a "Cannot issue commands other than SUBSCRIBE and UNSUBSCRIBE while channels are open" when the the .get() is hit:

scan_cache_server.subscribe(txn_scan_key)
chan_msgs_gen = scan_cache_server.listen()
chan_msgs_gen.next()
scan_cache_server.unsubscribe()
master_result = scan_cache_server.get(txn_scan_key)

Traceback (most recent call last):
master_result = scan_cache_server.get(txn_scan_key)
File "/git/charon/charon.py", line 1515, in do_content_scan
File "build/bdist.macosx-10.6-universal/egg/redis/client.py", line 549, in get
master_result = scan_cache_server.get(txn_scan_key)
return self.execute_command('GET', name)
File "build/bdist.macosx-10.6-universal/egg/redis/client.py", line 549, in get
File "build/bdist.macosx-10.6-universal/egg/redis/client.py", line 330, in execute_command
*_options
File "build/bdist.macosx-10.6-universal/egg/redis/client.py", line 306, in _execute_command
raise RedisError("Cannot issue commands other than SUBSCRIBE and "
return self.execute_command('GET', name)
File "build/bdist.macosx-10.6-universal/egg/redis/client.py", line 330, in execute_command
*_options
File "build/bdist.macosx-10.6-universal/egg/redis/client.py", line 306, in _execute_command
raise RedisError("Cannot issue commands other than SUBSCRIBE and "

Doesn't work for simple SET/GET

I can't get this to work AT ALL using your library. WinXpsp3 / python 2.6

I installed a redis server on a linux box. I can get set values on the server using its non-localhost IP. I get errors when attempting to use your library from a windows client.

This is the code I ran on the server

import redis
r=redis.Redis("10.41.19.4")
r.set("key","value")
'OK'
r.get("key")
u'value'

This is code I ran on the client after the above:

import redis
r=redis.Redis("10.41.19.4")
r.get("key")
Traceback (most recent call last):
File "", line 1, in
File "redis\client.py", line 497, in get
return self.execute_command('GET', name)
File "redis\client.py", line 296, in execute_command
*_options
File "redis\client.py", line 275, in _execute_command
self.connection.send(command, self)
File "redis\client.py", line 77, in send
self.connect(redis_instance)
File "redis\client.py", line 62, in connect
redis_instance._setup_connection()
File "redis\client.py", line 389, in _setup_connection
self.execute_command('SELECT', self.connection.db)
File "redis\client.py", line 296, in execute_command
*_options
File "redis\client.py", line 278, in _execute_command
return self.parse_response(command_name, **options)
File "redis\client.py", line 355, in parse_response
response = self._parse_response(command_name, catch_errors)
File "redis\client.py", line 315, in _parse_response
raise ResponseError(response)
redis.exceptions.ResponseError: unknown command

Cannot reconnect (auth/select) if subscribed==True

If we are in "subscribed" mode (after doing a subscribe or psubscribe), and if the connection need to be reopened, it's not possible because AUTH (if password given) and SELECT are not in SUBSCRIPTIONS_COMMAND.

Is the good way to intercept the exception and then reauth et resubscribe ?

issue with SUBSCRIBE and pipes

Sample code:

redis = Redis()

# If I enable this line it works (i.e. executing any redis command before executing the pipe). This shouldn't be required though.
#redis.exists('z')

pipe = redis.pipeline()
pipe.subscribe('z')
print 'exec', pipe.execute()

for msg in pipe.listen():
    print msg


Output:

Traceback (most recent call last):
  File "sub.py", line 14, in 
    print 'exec', pipe.execute()
  File "/home/tom/lib/redis/client.py", line 1151, in execute
    return execute(stack)
  File "/home/tom/lib/redis/client.py", line 1113, in _execute_transaction
    self.connection.send(all_cmds, self)
  File "/home/tom/lib/redis/client.py", line 81, in send
    self.connect(redis_instance)
  File "/home/tom/lib/redis/client.py", line 66, in connect
    redis_instance._setup_connection()
  File "/home/tom/lib/redis/client.py", line 395, in _setup_connection
    self.execute_command('SELECT', self.connection.db)
  File "/home/tom/lib/redis/client.py", line 302, in execute_command
    **options
  File "/home/tom/lib/redis/client.py", line 1100, in _execute_command
    command_name, command, **options)
  File "/home/tom/lib/redis/client.py", line 278, in _execute_command
    raise RedisError("Cannot issue commands other than SUBSCRIBE and "
redis.exceptions.RedisError: Cannot issue commands other than SUBSCRIBE and UNSUBSCRIBE while channels are open

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.