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语句
1
2
3
>>>fromlupaimportLuaRuntime
>>>lua=LuaRuntime()
>>>lua.eval('1+1')
三、python中调用lua函数
Lupa将LuaJIT集成到了Python模块中,可以在Python中执行Lua代码。
下面提供一个.py 调用 .lua 中函数的demo,其中使用了lua的回调函数。如果只是需要简单函数,只需要在变量 g 中 按照名字找到函数的映射就可以了。
Test.lua
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
functiontest1(params)
return'test1:'..params
end
functiontest2(params)
return'test2:'..params
end
--入口函数,实现反射函数调用
functionfunctionCall(func_name,params)
localis_true,result
localsandBox=function(func_name,params)
localresult
result=_G[func_name](params)
returnresult
end
is_true,result=pcall(sandBox,func_name,params)
returnresult
end
Test.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
importtraceback
fromlupaimportLuaRuntime
importthreading
classExecutor(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
defrun(self):
try:
# 执行具体的函数,返回结果打印在屏幕上
luaRuntime=self.getLuaRuntime()
rel=luaRuntime(self.api,self.params)
printrel
exceptException,e:
printe.message
traceback.extract_stack()
defgetLuaRuntime(self):
"""
从文件中加载要执行的lua脚本,初始化lua执行环境
"""
# 上锁,保证多个线程加载不会冲突
ifExecutor.lock.acquire():
ifExecutor.luaRuntimeisNone:
fileHandler=open('./test.lua')
content=''
try:
content=fileHandler.read()
exceptException,e:
printe.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()
returnExecutor.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 的映射
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
importlupa
fromlupaimportLuaRuntime
lua=LuaRuntime(unpack_returned_tuples=True)
defpy_func(p):
printp
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
下面的这个例子也是类似的
1
2
3
4
5
6
7
8
>>>fromlupaimportLuaRuntime
>>>lua=LuaRuntime()
>>>lua.eval('1+1')
>>>lua_func=lua.eval('function(f, n) return f(n) end')
>>>defpy_add1(n):returnn+1
>>>lua_func(py_add1,2)
>>>lua.eval('python.eval(" 2 ** 2 ")')==4#True
>>>lua.eval('python.builtins.str(4)')=='4'#True
多找一些开源社区吧,相关的资料还是挺多的。