lua与python均为成熟的脚本方案,它们的不同在与体量,Lua的体量小,高效的执行方式适合嵌入式,python胶水的强大不言而喻。那么如果自己已经有了lua脚本的解决方案,python能否调用呢?答案是肯定的,这篇博客将介绍python中集成的lua环境包:lupa,简单介绍该工具的使用。
一、安装lupa
在线安装: pip install lupa
离线安装:下载离线包 https://pypi.org/project/lupa/#files
选择对应平台的离线包下载后使用pip进行安装
二、使用lupa再python中执行lua语句
lua.eval 可以直接执行lua语句
>>> from lupa import LuaRuntime
>>> lua = LuaRuntime()
>>> lua.eval('1+1')
三、python中调用lua函数
Lupa将LuaJIT集成到了Python模块中,可以在Python中执行Lua代码。
下面提供一个.py 调用 .lua 中函数的demo,其中使用了lua的回调函数。如果只是需要简单函数,只需要在变量 g 中 按照名字找到函数的映射就可以了。
Test.lua
function test1(params)
return 'test1:'..params
end
function test2(params)
return 'test2:'..params
end
-- 入口函数,实现反射函数调用
function functionCall(func_name,params)
local is_true,result
local sandBox = function(func_name,params)
local result
result = _G[func_name](params)
return result
end
is_true,result= pcall(sandBox,func_name,params)
return result
end
Test.py
import traceback
from lupa import LuaRuntime
import threading
class Executor(threading.Thread):
"""
执行lua的线程类
"""
lock = threading.RLock()
luaScriptContent = None
luaRuntime = None
def __init__(self,api,params):
threading.Thread.__init__(self)
self.params = params
self.api = api
def run(self):
try:
# 执行具体的函数,返回结果打印在屏幕上
luaRuntime = self.getLuaRuntime()
rel = luaRuntime(self.api, self.params)
print rel
except Exception,e:
print e.message
traceback.extract_stack()
def getLuaRuntime(self):
"""
从文件中加载要执行的lua脚本,初始化lua执行环境
"""
# 上锁,保证多个线程加载不会冲突
if Executor.lock.acquire():
if Executor.luaRuntime is None:
fileHandler = open('./test.lua')
content = ''
try:
content = fileHandler.read()
except Exception, e:
print e.message
traceback.extract_stack()
# 创建lua执行环境
Executor.luaScriptContent = content
luaRuntime = LuaRuntime()
luaRuntime.execute(content)
# 从lua执行环境中取出全局函数functionCall作为入口函数调用,实现lua的反射调用
g = luaRuntime.globals()
function_call = g.functionCall
Executor.luaRuntime = function_call
Executor.lock.release()
return Executor.luaRuntime
if __name__ == "__main__":
# 在两个线程中分别执行lua中test1,test2函数
executor1 = Executor('test1','hello world')
executor2 = Executor('test2','rudy')
executor1.start()
executor2.start()
executor1.join()
executor2.join()
在使用 g.function 直接调用lua函数的时候,返回值就直接是 lua脚本 中的返回值,还是非常友好的,如果遇到table返回值,在python中类型就是luaTable,直接按照下标索引就可以了。
四、lua调用python
由于lua中不能出现python的变量,所以lua调用python只能使用lua.eval来执行一个匿名的定义,建立一个函数映射关系,来进行调用。
下面这个demo中的 lua.eval 就是返回一个lua_call 到 py_call 的映射
import lupa
from lupa import LuaRuntime
lua = LuaRuntime(unpack_returned_tuples=True)
def py_func(p):
print p
return 'hello '+str(p)
#execute无返回,打印出来是None
lua.execute('var_before=1;print(var_before);')
#eval返回的是一个lua call到py call的映射
pycall = lua.eval('function(pyfunc,param1) var_before=pyfunc(param1) end')
pycall(py_func,'world') # 打印world,返回的var_before = hello world
lua.execute('print(var_before)') # 打印 hello world
下面的这个例子也是类似的
>>> from lupa import LuaRuntime
>>> lua = LuaRuntime()
>>> lua.eval('1+1')
>>> lua_func = lua.eval('function(f, n) return f(n) end')
>>> def py_add1(n): return n+1
>>> lua_func(py_add1, 2)
>>> lua.eval('python.eval(" 2 ** 2 ")') == 4 #True
>>> lua.eval('python.builtins.str(4)') == '4' #True
多找一些开源社区吧,相关的资料还是挺多的。