为Zope提供Lua支持——兼Plone功能扩展方法

为Zope提供Lua支持


  本贴旨在说明如何为Zope提供Lua支持,即使得Zope中的Python脚本可以调用Lua格式的配置文件,甚或可以直接调用Lua脚本命令,从而为Zope提供更强大的功能。

一、Lua简介

  Lua是一种为支持有数据描述机制的一般过程式编程语言而设计的扩展编程语言。它同样可以对面向对象语言、函数式程序设计以及数据驱动编程提供很好的支持。做为一种嵌入式脚本语言,Lua非常小,速度很快,功能却非常强大。

  任何一种语言的存在都是为了表达,作为一个扩展语言,Lua提供给我们非常强大也非常的灵活的表达方式。Lua没有"Main"函数的概念:它仅仅是嵌入一个宿主程序进行工作,可以称之为 嵌入式编程 或者简单的说是 宿主编程。这个宿主程序可以调用函数来执行Lua的代码片断,可以设置和读取Lua的变量。Lua的能力可以扩展到更大范围,在不同的领域内,这样就在同样的语法框架下创建了你自定义的编程语言。

  Lua的一个重要的应用是做为一个配置语言。通常来说,对于应用程序中一些易变的数据,我们需要一种灵活的处理方式来支持它的改变,这种改变可以在运行时发生。有很多方法可以做到这一点,你可以选择通常的文本文件,ini文件,环境变量等等。Lua做为一种配置语言,可以提供给你更为强大和更为灵活的表达能力。

  使用Lua作为配置语言会给我们带来如下优势:

  1、使用Lua做为配置语言,由Lua处理所有的语法检查和错误处理。你的配置文件甚至可以有注释。

  2、用户可以写出更为复杂,更为灵活的配置来,甚至可以根据运行时的某个状态来确定配置。

  3、预期未来的配置是困难的,然而使用Lua可以让你的程序更容易的接受变化,使你的程序更有弹性。


二、Lua的安装

  将Lua的源码包lua-5.0.tar.gz上传到服务器上之后解压缩,然后在源码目录下键入如下命令:

# make
# make install

即可完成Lua的安装过程。

  安装结束后,Lua的相关文件将拷贝到系统目录中,具体如下所示:

cp bin/* /usr/local/bin
cp include/*.h /usr/local/include
cp lib/*.a /usr/local/lib
cp doc/*.1 /usr/local/man/man1


三、lunatic-python的安装

  lunatic-ptyhon是Python和Lua之间的双向桥梁,允许这两种语言进行交互。“双向”就意味着既可以在python中使用Lua,也在Lua中使用Python。

  将lunatic-ptyhon的产品包lunatic-python-1.0.tar.bz2上传到服务器上之后解压缩,这里需要注意下,该产品包的压缩格式为.tar.bz2,而不是常见的.tar.gz格式,因此解压缩参数也不再是常见的“tar -xzvf *.tar.gz”,而应使用“tar -jxvf *.tar.bz2”。

  解压缩之后在产品目录下键入如下命令:

# python setup.py install

即可完成该产品的安装过程。

  安装结束后,该产品的源码库将被拷贝系统目录中,具体如下所示:

copying build/lib.linux-i686-2.4/lua-python.so -> /usr/local/lib/python2.4/site-packages
copying build/lib.linux-i686-2.4/lua.so -> /usr/local/lib/python2.4/site-packages

  更多的lunatic-ptyhon说明参见此链接


四、产品测试

  按如下步骤进行测试,如果可以得到正确的结果,既说明Lua和lunaitc-python均已正确安装。

[root@localhost /]# python
Python 2.4.1 (#1, Jul 12 2005, 14:19:15) 
[GCC 3.4.3 20041212 (Red Hat 3.4.3-9.EL4)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import lua
>>> lg = lua.globals()
>>> lg.string
<Lua table at 0x9279148>
>>> lg.string.lower
<Lua function at 0x9279268>
>>> lg.string.lower("Hello World!")
'hello world!'

五、应用范例

  本范例中我们要读取的是物流跟踪系统的物流过程采集记录,该采集记录中含采集时间、采集模式、采集类型、采集代码以及采集备注。

  出于安全性的考虑,zope禁止用户在网站的ZMI页面下对文件系统进行操作,因此我们只能建立一个External Method来实现读取Lua配置文件。然后在网站的ZMI页面下添加相应的External Method即可在所需页面中调用该方法。

 

外部方法(External Method):

ID ParseLogisticsLog
Module Name ParseLogisticsLog
Function Name ParseLogisticsLog

Source Code

#!/usr/bin/python
# -*- coding: utf-8 -*-
#-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
#名字:ParseLogisticsLog
#摘要:实现从Lua格式的记录文件中读取数据的功能
#变量:upload —— 上传的Lua格式的记录文件中的数据
#返回:Lua记录文件中的指定数据表内容,返回类型为字典
#建立:lindalee@RunTo建立于2006年7月15日
#备注:此文件目前只能返回Lua记录文件中指定的数据表
#   因此要求必须了解Lua记录文件中的内容
#   目前尚未实现对Lua记录文件中全部变量的提取
#-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
def ParseLogisticsLog(upload):
  if not upload:
    return 0
  else:
    upload_data = upload.read()
    if len(upload_data)==0:
      return 1

  StartPos = upload_data.find('Logistics_Log')
  if (StartPos == -1):
    return 2

  import lua
  lua.globals().Logistics_Log = ""
  try:
    lua.execute(upload_data[StartPos:])
  except:
    return 3

  orgLog = lua.globals().Logistics_Log

  LogType = lua.execute("return type(Logistics_Log)")

  return ParseLog( orgLog, LogType )
#-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
#名字:ParseLog
#摘要:从Lua数据表变量中读取数据并转换为Python字典变量
#变量:orgLog —— Lua数据表
#返回:retLog —— Python字典
#建立:lindalee@RunTo建立于2006年7月16日
#-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
def ParseLog(orgLog, lType):
  import lua

  #retLogs = {}
  #retLogs["type"] = lType
 
  if (lType!="table"):
    retLog = orgLog
  else:
    retLog = {} 
    lua.globals().orgLog = orgLog
   
    luaCmd = """
             logTypes = {};
             for key in orgLog do
               logTypes[key] = type(orgLog[key])
             end
             """
    lua.execute(luaCmd)

    logTypes = lua.globals().logTypes

    for key in orgLog:
      retLog[key] = ParseLog(orgLog[key], logTypes[key])

  return retLog
#-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

 

应用范例:

ID test_UploadLua

Source Code

<html metal:use-macro="here/main_template/macros/master">
<div metal:fill-slot="main">
<body>
<br><br>
<center>
<form action="test_ShowLua" method="post" enctype="multipart/form-data">
  <input type=file name="upload">
  <input type=submit value="解析此Lua文件">
</form>
</center>
<br>
</body>
</div>
</html>

 

ID test_ShowLua
Parameter List upload

Source Code

"""
名字:test_ShowLua
摘要:对用户上传的Lua记录文件中的进行数据提取并提取其中的记录
变量:upload —— 用户上传的Lua记录文件
返回:Lua记录文件中的指定数据表内容
建立:lindalee@RunTo建立于2006年8月2日
备注:本范例脚本调用了外部方法ParseLogisticsLog
   使用前请确认已将该对象正确导入至可引用位置
"""
request = container.REQUEST
response =  request.RESPONSE

response.setHeader("Content-type","text/html;charset=utf-8")

#读取用户上传的Lua记录文件中的数据
LogisticsLog = context.ParseLogisticsLog(upload)

#判断读取是否是否成功
if LogisticsLog==0:
  ErrStr = context.UrlEnCode("未选定文件,请选定文件后再选择上传!")
  response.redirect(context.absolute_url()+ \
                    '/test_UploadLua?portal_status_message=' + ErrStr)
  return 0
elif LogisticsLog==1:
  ErrStr = context.UrlEnCode("选定文件为空文件,请重新上传!")
  response.redirect(context.absolute_url()+ \
                    '/test_UploadLua?portal_status_message=' + ErrStr)
  return 0
elif LogisticsLog==2:
  ErrStr = context.UrlEnCode("选定文件中未包含所需记录,请重新上传!")
  response.redirect(context.absolute_url()+ \
                    '/test_UploadLua?portal_status_message=' + ErrStr)
  return 0
elif LogisticsLog==3:
  ErrStr = context.UrlEnCode("选定文件为无效文件,请重新上传!")
  response.redirect(context.absolute_url()+ \
                    '/test_UploadLua?portal_status_message=' + ErrStr)
  return 0

print "<br>该文件中记录物流数据如下:<br><br>"

print "<table border=1>"
print "<tr>"
print "<th>采集时间</th>"
print "<th>采集模式</th>"
print "<th>采集类型</th>"
print "<th>采集代码</th>"
print "<th>采集备注</th>"
print "</tr>"

for n in LogisticsLog.keys():
  print "<tr>"
  print "<td>" + DateTime(LogisticsLog[n]["Time"]).strftime('%Y年%m月%d日 %H:%M:%S') + "</td>"

  if (LogisticsLog[n]["Mode"] == 1):
    print "<td>入库</td>"
  elif (LogisticsLog[n]["Mode"] == 2):
    print "<td>出库</td>"
  elif (LogisticsLog[n]["Mode"] == 3):
    print "<td>退货</td>"
  else:
    print "<td>未知</td>"

  if (LogisticsLog[n]["Type"] == 1):
    print "<td>按垛</td>"
  elif (LogisticsLog[n]["Type"] == 2):
    print "<td>按箱</td>"
  elif (LogisticsLog[n]["Type"] == 3):
    print "<td>按瓶</td>"
  else:
    print "<td>未知</td>"

  print "<td>" + LogisticsLog[n]["Code"] + "</td>"

  if (LogisticsLog[n]["Mode"] == 2):
    print "<td>"
    print "销售地区:" + LogisticsLog[n]["Note"]["Zone"] + "<br>"
    print "销售公司:" + LogisticsLog[n]["Note"]["Company"]
    print  "</td>"
  else:
    print "<td>" + LogisticsLog[n]["Note"] + "</td>"

  print "</tr>"

print "</table>"

return printed

 

来源: http://write.blog.csdn.net/postedit/8742344

你可能感兴趣的:(为Zope提供Lua支持——兼Plone功能扩展方法)