由于错误的类型比较,redis lua无法正常工作

时间:2018-01-04 02:10:54

标签: lua redis

我想通过在python中使用redis lua脚本减少我的存储空间,我的代码如下:

def lua_storage():
conn = redis_conn()
lua = """
        local storage = redis.call('get','storage')
        if  (storage ~= nil) then
            if tonumber(storage) >= 0 then
                return redis.call('decr','storage')
            else
                return 'storage is zero now, can reply decr action'
            end
        else
            redis.call('set','storage',10)
        end
        """
result = conn.eval(lua,0)
print(result)

上面的代码很简单,它是一个控制好存储的lua脚本,如果好的没有存储,脚本会将其stroage设置为10,当用户访问这个脚本时,存储将减少1直到当存储为0时,用户将获得“现在存储为零,可以回复decr动作”消息。

当我在python中运行此方法时,我得到以下异常:

Traceback (most recent call last):
File "D:/mytools/luaredis/mytest.py", line 53, in <module>
lua_storage()
File "D:/mytools/luaredis/mytest.py", line 47, in lua_storage
result = conn.eval(lua,0)
File "C:\Python27\lib\site-packages\redis\client.py", line 2067, in eval
return self.execute_command('EVAL', script, numkeys, *keys_and_args)
File "C:\Python27\lib\site-packages\redis\client.py", line 668, in execute_command
return self.parse_response(connection, command_name, **options)
File "C:\Python27\lib\site-packages\redis\client.py", line 680, in parse_response
response = connection.read_response()
File "C:\Python27\lib\site-packages\redis\connection.py", line 629, in read_response
raise response
redis.exceptions.ResponseError: Error running script (call to f_19dc8de385a024db32cb227ec869e8b644ebbc36): @user_script:4: user_script:4: attempt to compare number with nil 

我试图弄清楚问题,但找不到它。 对于上面的代码本身,我不认为它有一些错误(我跟着this answer编写我的代码)。我唯一想确定的是,redis和lua的返回类型是否不同导致了这个异常?

我应该遵循调试此脚本的任何好的调试方法?

---- ---- EDIT

对于我的同事卡罗尔来说,我改变了下面的代码并得到了正确的结果:

def lua_storage():
conn = redis_conn()
lua = """
        if redis.call('get','storage') then
            if tonumber(redis.call('get','storage')) > 0 then
                return redis.call('decr','storage')
            else
                return 'storage is zero now, can reply decr action'
            end
        else
            redis.call('set','storage',10)
        end
        """
result = conn.eval(lua,0)
print(result)

这是另一个问题,我们丢弃本地存储变量,直接使用 redis.call('get','storage')。 所以我不知道为什么本地存储不会做这些事情。需要做更多的工作。

凯文的Thx,终于得到了以下代码:

def lua_storage():
conn = redis_conn()
lua = """
        local storage = redis.call('get','storage')
        if  storage ~= false then
            if tonumber(storage) > 0 then
                return redis.call('decr','storage')
            else
                return 'storage is zero now, can reply decr action'
            end
        else
            return redis.call('set','storage',10)
        end
        """
result = conn.eval(lua,0)
print(result)

因为存储在第一个时为nil,而在if语句中为nil,所以它将返回false,因此我们需要将nil更改为false。

2 个答案:

答案 0 :(得分:2)

根据Redis Lua documentationproject editor Redis值变为nil Lua值:

  

Redis Nil批量回复和Nil多批量回复 - &gt; Lua false布尔类型

因此,您应该将falseGET的结果进行比较,而不是false。您之后看到此特定邮件,因为niltonumber(false),然后您与nil号码进行比较。

答案 1 :(得分:0)

错误消息说明了问题:

  

user_script:4:user_script:4:尝试将数字与nil进行比较

存储是一个无法比较的数字。

代码可以这样写:

"""
          if  redis.call('get','storage') then
            local storage = redis.call('get','storage')
            if tonumber(storage) >= 0 then
                return redis.call('decr','storage')
            else
                return 'storage is zero now, can reply decr action'
            end
        else
            redis.call('set','storage',10)
        end
        """