Python通过Django搭建网站执行Lua脚本 (实现数据解析)

Python通过Django搭建网站执行Lua脚本 (实现数据解析)

论如何优雅的进行Python与Lua交互,当然方法有多种,但很多仅凭纯Script操作不是很爽,本文就通过网页形式实现,实际操作来讲,有个网页UI操作也会方便很多。

一、问题背景和解决

  • 背景: 之前某IoT项目,Device端与Cloud/App端数据通讯Protocol包括Binary、Json格式,全部由lua进行解析(实际是binary与json格式之间相互转换,是由于某系列设备只能用binary),但Lua脚本出bug不好排查,特别是App/Cloud/Device三方联调中要核对一堆消息,有个符号错了都会导致解析失败

  • 问题:我们作为Device端开发人员写的Lua脚本,需要部署到Cloud的Paas上,该类Device上下行的数据都要通过Lua进行Binary - Json互转,才能正确处理,因此Lua出了问题,App/Cloud team需要把消息发给我们本地执行lua后,再和App/Cloud 检查消息, 非常麻烦,当然我是懒人,这么麻烦的也忍不了。

  • 解决:使用Django搭个Bin-Json消息转换网站,App/Cloud/Device三方通过网站对消息数据 执行lua解析转换,检查各方数据是否有误。

项目使用的lua脚本只能在linux环境执行, 所以也做不了exe,所以通过网页形式开放给各开发人员,是最快捷方便的。

二、执行Lua效果预览

• Json转Binary:(会自动识别消息类型进行转换)
Python通过Django搭建网站执行Lua脚本 (实现数据解析)_第1张图片
• Binary转Json:

Python通过Django搭建网站执行Lua脚本 (实现数据解析)_第2张图片

如果解析失败,Django的console里也可以看error log:
Python通过Django搭建网站执行Lua脚本 (实现数据解析)_第3张图片

  • 登录界面

Python通过Django搭建网站执行Lua脚本 (实现数据解析)_第4张图片
Django登录页面来自于: 刘江的Django教程

三、主要代码解析:

translate.py

translate.py接收Bin-Json转换页面 输入框的待转换消息,写入到msgInput.txt,
然后通过调用subprocess 的check_output执行 luaParser.lua(消息解析脚本)进行转换,并将转换完成的消息写入 msgOutput.txt, 最后将转换后的结果传回页面显示。

# -*- coding: utf-8 -*-
 
from django.shortcuts import render
from django.views.decorators import csrf
from django.shortcuts import redirect

#from translator import translator
import subprocess as ss
import sys
import traceback

msgInput_FileName = "msgInput.txt"
msgOutput_FileName = "msgOutput.txt"


def WritetoFile(FileName,Data):
    #fileName= 'record.txt'
    with open(FileName,'w') as record:
        strr = ""
        content = strr.join(Data)
        record.write(content+'\n')
        
def ReadFile(FileName):
    fileName = FileName
    with open(fileName) as record:
        lines = record.read().splitlines()
        #print(lines)
        return lines
 
# handle POST request data
def translate_post(request):
    if not request.session.get('is_login', None):
        return redirect('/login/')
    
    ctx ={}
    if request.POST:
        #Get input from post
        MsgInput  = request.POST['q']
        print('Input from WebPage is:'+MsgInput)
        WritetoFile(msgInput_FileName, MsgInput)
        message = '输入为空, 请检查填写的内容!'
        
        #input check
        if MsgInput.strip():
            try:
                luaPrint = ss.check_output(['lua luaParser.lua'],shell=True)
                #print (luaPrint)
                Msgoutput = ReadFile(msgOutput_FileName)
                #print (Msgoutput)
            except ss.CalledProcessError as exc:  
                print(exc.returncode)
                print(exc.output)
                #Error log
                tblog = traceback.format_exc()
                Msgoutput = 'Error in Lua:'+str(exc.output)
                Msgoutput+= '.....................ErrorCode is:'+ str(exc.returncode)
                Msgoutput+= '.....................ErrorLog is:'+ tblog
        
            ctx['rlt'] = Msgoutput
            ctx['msgInput'] = MsgInput
            
            #return a dictionary
            return render(request, "login/index.html", ctx)
        else:
            return render(request, "login/index.html", {'message': message})

    return render(request, 'login/index.html', locals())


if __name__ == '__main__':
    if(sys.argv[1:] == []):
        print('Not input parameter , Use latest Data in msgInput.txt...')
    else:
        MsgInput = sys.argv[1]
        WritetoFile(msgInput_FileName, MsgInput)
        

msgInput.txt和msgOutput.txt文件作为消息数据缓存:

在这里插入图片描述

LuaParser.lua

luaParser.lua读取msgInput.txt判断输入消息是binary 还是json数据,然后调用相应的script进行转换,转换后的数据写入msgOutput.txt,供页面显示

--Howard Xue , 20190322

launch = require'decode_launch'
code = launch'xxxchinaxxx.lua'

msgInput_FileName = "msgInput.txt"
msgOutput_FileName = "msgOutput.txt"

-- File Operation
function readMsgfile(filename)  
	file = io.open(filename, "r")

	MsgRead = file:read()
	--print(MsgRead)

	file:close()
end 


function writeMsgfile(path, content)
   mode = "w+"
   local file = io.open(path, mode)
   if file then
     if file:write(content) == nil then return false end
     io.close(file)
     return true
   else
     return false
 end
end


-- Main begin

isBin2Json = isMsgData_Binary(msgInput_FileName)

readMsgfile(msgInput_FileName)

if isBin2Json == true then
-- Hex to Json
	print(" Bin --> Json :")
	outputData = code.convertFromDevice(code.hex(MsgRead))
	writeMsgfile(msgOutput_FileName, outputData)
	print(outputData)
else
--Json to Hex
	print(" Json --> Bin :")
	--print(code.hexDump(code.convertToDevice(MsgRead)))
	outputData = code.hexDump(code.convertToDevice(MsgRead))
	writeMsgfile(msgOutput_FileName, outputData)
	print(outputData)
end


--readMsgfile(msgOutput_FileName)
--print(MsgRead)

-- Hex to Json
--print("Msg Output is:")
--print(code.convertFromDevice(code.hex(MsgRead)))


Bin-Json转换页面

login/index.html,在输入框内输入待转换的数据后,点击一键转换,submit数据到translate.py, 并将转换后的结果(rlt 即msgOutput)显示出来。

{% load static %}
<!DOCTYPE html>
<html lang="en">
  <head>
    <!-- Required meta tags -->
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">

    <!-- Bootstrap CSS -->
      <link href="https://cdn.bootcss.com/twitter-bootstrap/4.3.1/css/bootstrap.min.css" rel="stylesheet">
      <link href="{% static 'login/css/login.css' %}" rel="stylesheet" />

    <title>Bin-Json转换</title>
  </head>
<body>


<br><br />

  <div class="container">
  
  <h1 style="color:#FFFFF0">{{ request.session.user_name }}!  欢迎回来! </h1>
  
  <p>
    <a style="color:#F08080" href="/logout/">退出登录</a>
  </p>
<br> <br />
            <div class="col">
			  
			   <form action="/translate/" method="post">
					{% csrf_token %}
					{% if message %}
                      <div class="alert alert-warning">{{ message }}</div>
					{% endif %}
					
					<input type="text" name="q" style="width:800px;height:50px;font-size:15px" placeholder="输入二进制或json消息" autofocus >
					<!-- <input type="submit" value="Submit"> -->
					 <button type="submit" class="btn btn-primary">一键转换</button>
			   </form>
			   
			   <div style="color:#FFFF00;word-break:break-all">: 如果转换结果为Error, 请检查输入数据正确性,以及脚本是否报错</div>
            </div>
			
			
				<div style="font-family:verdana;padding:20px;border-radius:10px;border:5px solid #EE872A;">
				
						<h3>Result:</h3>

						<div style="color:#000000;word-break:break-all">{{ rlt }}</div>

				</div>
				<br><br/>
				<div style="font-family:verdana;padding:20px;border-radius:10px;border:5px solid #EE872A;">
				
						<h3>Input:</h3>

						<div style="color:#000000;word-break:break-all">{{ msgInput }}</div>

				</div>
  </div> <!-- /container -->

    <!-- Optional JavaScript -->
    <!-- jQuery first, then Popper.js, then Bootstrap JS -->

    <script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"></script>
    <script src="https://cdn.bootcss.com/popper.js/1.15.0/umd/popper.min.js"></script>
    <script src="https://cdn.bootcss.com/twitter-bootstrap/4.3.1/js/bootstrap.min.js"></script>

</body>
</html>

urls.py

添加translate URL对应关系

from django.contrib import admin
from django.conf.urls import url
from django.urls import path
from django.urls import include
from login import views, translate

urlpatterns = [
    path('admin/', admin.site.urls),
    path('index/', views.index),
    path('login/', views.login),
    path('register/', views.register),
    path('logout/', views.logout),
    path('confirm/', views.user_confirm),
    path('captcha/', include('captcha.urls')),
  
    path('translate/', translate.translate_post),
]

其他好玩的python脚本

Python实现自动发送邮件 --自动抓取博客/网站中留言的邮箱并发送相应邮件
Python自动生成代码 - 通过tkinter图形化操作并生成代码框架
Python解析CSV数据 - 通过Pandas解析逻辑分析仪导出的CSV数据
Python通过Django搭建网站执行Lua脚本 (实现数据解析)

你可能感兴趣的:(Python)