I wish to pass a number of keys and values from python to a lua script, via redis's eval function which is documented as:
eval(script, numkeys, *keys_and_args)Execute the Lua
script, specifying thenumkeysthe script will touch and the key names and argument values inkeys_and_args. Returns the result of the script.In practice, use the object returned by
register_script. This function exists purely for Redis API completion.
I am following this answer as a starting point. That script increment the scores of all values in the sorted set specified by 1. As I wish to specify the values to update (key names) and the increment count for each (argument values) my script looks like this:
-- some logging
local loglist = "lualog"
redis.pcall("DEL", loglist)
local function logit(msg)
redis.pcall("RPUSH", loglist, msg)
end
logit("started")
-- count & log the keys provided
local countofkeys = table.getn(KEYS)
logit(countofkeys)
-- loop through each key and increment
for n = 1, countofkeys do
redis.call("zincrby", "test_set", ARGV[n], KEYS[n])
end
I can run this from the command line with:
$ redis-cli --eval script.lua apple orange , 1 1
Then in Python confirm that the values have incremented:
>>> r.zrange('test_set', start = 0, end = -1, withscores=True)
[(b'apple', 1.0), (b'orange', 1.0)]
However I don't know how to run this using eval:
>>> c.eval(script,1,{'orange':1,'apple':1})
redis.exceptions.DataError: Invalid input of type: 'dict'. Convert to a byte, string or number first.
>>> c.eval(script,2,'apple orange , 1 1')
redis.exceptions.ResponseError: Number of keys can't be greater than number of args
>>> c.eval(script,1,'apple orange , 1 1')
redis.exceptions.ResponseError: Error running script (call to f_aaecafd58b474f08bafa5d4fefe9db98a58b4084): @user_script:21:
@user_script: 21: Lua redis() command arguments must be strings or integers
The documentation isn't too clear on what keys_and_args should look like. Also at the comand line numkeys isn't actually required by the looks of things. Does anyone know what this should look like?
Bonus question: How to avoid hard coding "test_set" into the lua script.
*keys_and_args should be an iterable (e.g. a list) - the use of an asterisk as a prefix to the argument's name is the Pythonic way of saying that.
Bonus tip: look into redis-py Script helper.
Bonus answer: Any key names touched by the script need to be provided via the KEYS table. Your script is doing it all wrong - read the documentation about EVAL.
Also at the comand line numkeys isn't actually required by the looks of things
This is only with the cli when used in that fashion - the comma (',') delimits between key names and arguments.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With