(6)LUA程序设计-编译执行与错误(compile 、run & error)处理

1.编译问题

----------------------------

----------------------------

首先我们谈一下编译的问题,LUA的执行,是将源代码转换成中间代码的形式执行的。

说到这里,也许会有不少人会问,LUA不是一种解释型语言,没错!LUA就是一门解释型动态语言脚本。其实区别一门语言是否为解释型语言,关键在不在于它是否被编译,而是它的编译器是否是运行时库的一部分,是否具备动态执行代码的能力。所以LUA是代码是需要被转成中间代码被LUA编译器执行的。

1.1LUA当中的常见编译函数

1.1.1 loadfile

LUA中,有dofile这样子函数,用于加载LUA代码文件,用法:dofile(filename), eg.dofile('xxx.lua');但其实dofile是调用了更深层的loadfile函数,与dofile类似,loadfile同样是用于加载编译一个代码块(chunck),但是除此之外loadfile还返回一个函数,同时如果编译出错,loadfile还会返回nil及相关错误信息。dofile调用loadfile的代码如下:

funciton dofile(filename)

local f = assert(loadfile(filename));

return f();

end

说明:1.assert用判断loadfile是否成功,有点像java/javascript里边的一个try{}catch{},用以引发错误信息。

2.dofile相对loadfile来说,每次调用,都需要重新编译一次被加载的代码块,而一次调用loadfile可以多次调用loadfile返回的函数引用。

1.1.2 loadstring

与loadfile类似,loadstirng 是用于加载lua代码块的字符串形式,并返回由该代码块组成的一个函数。

如:f = loadstring("i = i+1");

i = 0;

f() -->1

f()-->2

上面等价于

i = 0;

loadstring("i = i+1")( );-->1

loadstring("i = i+1")( );-->2

为了让错误显示得更清楚,我们可以为loadstring 的返回值加上 assert,即 assert(loadstring(s))()的形式

LUA将所以有独立的代码块都看成是一个匿名函数的函数体,而函数有可变参数这个特征(前面讲到的三大特征之一),所以loadstring函数所返回的函数,也允许传入参数。只需要在loadstirng(s)的s当中声明一个local变量用于保存可变参数,即可

f = loadstring("local xx = ... return xx "); f('hello') -- hello

------------------------------------------

注:f = loadstring('i = i+1') 基本上等价于 f = function() i = i+1 end

但是两者有极大的区别:

1.从词法域上来讲,loadstring 的方式,不涉及词法域,举例如下

i = 32

local i = 0

f = loadstring("i = i+ 1");

g = function() i=i+1 end;

f() --33

g() -- 1

2.从编译次数的角度来说,loadstring 每次调用都要重新编译一次,而function的形式,只编译一次。

1.1.3 load

与loadfile和loadstring相比,load函数有所不同。loadfile和loadstring 是分别从文件和字符串中读取程序块,但load则不同,如果加载的代码块过大,内存空间不够,用load则可以解决问题,它接收一次读取器函数,可以将一个程序块分多几读取,通过反复调用“读取器函数”,直到返回nil为止。

1.1.4 loadlib

众所周知,动态链接机制并非ansi c 标准的一部分,LUA用C编写的,不会包含无法用ANSI C实现的所有机制,但是动态链接机制除外,LUA将动态链接机制作为实现其他机制的母机制,通过动态机制,LUA可以加载任何LUA不支持的机制。

LUA加载动态链接库,主要用到函数package 下的loadlib,用法如下

local dynaLinkLibPath = ''/usr/local/lib/lua/5.0/socket.so' --linux下动态链接库后缀为so

local f = package.loadlib(path,'luaopen_socket');

package.loadlib通过指定加载库的路径,以及C函数名,返回一个LUA函数,用以被LUA代码调用。loadlib将结合我们后面要讲的require函数使用,require用于搜索指定库,loadlib用于加载搜到的库。

2.错误处理,异常封装,错误跟踪

2.1 LUA当中错误处理一般情况是

f = io.open(file);

if not f then

<error code here>

else

....

end

当然LUA提供了一个内建引发错误的函数,即上面讲到的assert函数

它接收到两个参数,第一个参数是lua的代码块,可以是一个表达式,一个函数调用的返回结果,第二个参数是一个字符串,用于提供 第一个参数代码执行时出错的提示


2.2异常封装

LUA提供一种pcall保护模式,pcall是一个函数,参数是一个函数,pcall返回两个值,第一个是函数参数是否调用成功,调用失败返回false,否则返回true.第二个参数是调用失败的错误信息。

local status ,err = pcall(function() error({code=500}) end);--可以自定义出错代码

print(err.code)--打印出错代码

2.3 错误跟踪

error()函数,可以接收一个字符串参数,用于提示出错原因,如error("the wrong string unexpected!!");,也可以接收两个参数,第一个参数用于提示出错原因,第二个参数用于表示具体出错的级别,可以跟踪错误出现的位置。举例如下:

function fuck(s)

if type(s) ~= 'string' then

error('string expected!!')

else ....

end

如果主函数调用了fuck()函数,并传入一个122number类型的数值,fuck将出错,但是并不能显示出错的层次,并不知道出错在哪里,所以将上面代码改成

function fuck(s)

if type(s) ~= 'string' then

error('string expected!!',2)

else ....

end

注:在error函数加入第二个参数2,那么出错时将提示具体出错的位置,便于调试跟踪!!!


完毕!!下节将讲解lua程序设计基础篇的最后一小节,内容也是相当重要!!也难理解!!

----------------好了---本节到此结束,下一节将讲解-(7)LUA程序设计-协同程序(coroutine)------------

LUA技术交流群,请加Q群:139315537,加入请注明来源。

(1)LUA程序设计-开篇(beginning)(2012-07-28 00:47)
(2)LUA程序设计-类型与值(type & value)(2012-07-28 23:12)
(3)LUA程序设计-表达式与语句(expression & statement)(2012-07-29 22:51)


(4)LUA程序设计-函数及深入理解(function)(2012-08-03 23:00)


(5)LUA程序设计-迭代器(state iterator & stateless iterator)(2012-08-06 23:05)
(6)LUA程序设计-编译执行与错误(compile 、run & error)处理(2012-08-11 00:05)
(7)LUA程序设计-协同程序(coroutine)(2012-09-01 00:06)

### 如何在Python中使用LuaLaTeX或实现PythonLuaLaTeX的集成 要在Python中调用LuaLaTeX或将两者集成在一起,可以采用多种方法来完成这一目标。以下是几种常见的技术手段及其具体实现方式: #### 方法一:通过子进程调用LuaLaTeX 最简单的方法是利用Python的标准库 `subprocess` 来运行外部命令并传递参数给LuaLaTeX编译器。 ```python import subprocess def compile_lualatex(input_file, output_dir=&quot;.&quot;): command = [ &quot;lualatex&quot;, # LuaLaTeX 编译器名称 &quot;-output-directory=&quot; + output_dir, input_file # 输入文件名(带扩展名) ] try: result = subprocess.run(command, check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) print(result.stdout.decode()) # 输出日志信息 except subprocess.CalledProcessError as e: print(f&quot;An error occurred while compiling {input_file}: {e.stderr.decode()}&quot;) # 调用示例 compile_lualatex(&quot;example.tex&quot;) # 假设有一个名为 example.tex 的 LaTeX 文件 ``` 这种方法适用于大多数场景,并且能够很好地控制输入输出路径以及错误处理[^1]。 --- #### 方法二:借助第三方库 PyLaTeX 或 TexSoup 实现更高级的功能 如果希望进一步简化操作流程或者增强灵活性,则可以选择一些专门设计用来生成 TeX 文档的 Python 库,比如 **PyLaTeX** 和 **TexSoup**。 ##### 使用 PyLaTeX 创建文档并通过 LuaLaTeX 渲染 PyLaTeX 提供了一种面向对象的方式来构建复杂的 PDF 报告或其他类型的出版物。 ```python from pylatex import Document, Section, Subsection, Command from pylatex.utils import bold doc = Document(default_filepath=&quot;mydocument&quot;) with doc.create(Section(&#39;A section&#39;)): doc.append(bold(&#39;Some Text&#39;)) # 设置编译引擎为 lualatex doc.preamble.append(Command(&#39;usepackage&#39;, &#39;fontspec&#39;)) # 需要 XeLaTeX/LuaLaTeX 支持字体设置 doc.generate_pdf(clean_tex=False, compiler=&#39;lualatex&#39;) # 显式指定 lua latex作为编译工具链的一部分 ``` 上述代码片段展示了如何定义基本结构并将最终产物导出成支持 Unicode 字体渲染等功能丰富的 PDF 文件[^2]。 --- #### 方法三:嵌入 LuaLaTeX 到 PyQt GUI 中 对于那些正在开发图形界面应用程序的人来说,可能还需要考虑将整个过程封装到按钮点击事件当中去。下面是一个简单的例子说明怎样结合异步编程模型让长时间运行的任务不会阻塞主线程体验。 ```python import sys from PyQt5.QtCore import QObject, QThread, pyqtSignal from PyQt5.QtWidgets import QApplication, QPushButton, QVBoxLayout, QWidget class Worker(QObject): finished = pyqtSignal() progress = pyqtSignal(int) def run(self): &quot;&quot;&quot;Long-running task.&quot;&quot;&quot; import time for i in range(5): # Simulate some work being done. self.progress.emit(i * 20) # Emit signal indicating percentage complete. time.sleep(1) # Artificial delay simulating computation. from subprocess import call call([&quot;lualatex&quot;, &quot;--interaction=batchmode&quot;, &quot;yourfile.tex&quot;]) # Replace with actual file name/path self.finished.emit() app = QApplication(sys.argv) window = QWidget() layout = QVBoxLayout() button = QPushButton(&quot;Compile LuaLaTeX Document&quot;) layout.addWidget(button) worker_thread = None def start_task(): global worker_thread button.setEnabled(False) thread = QThread(parent=window) worker = Worker() worker.moveToThread(thread) worker.finished.connect(lambda: finish_task()) worker.progress.connect(report_progress) thread.started.connect(worker.run) thread.start() worker_thread = thread progress_label = QLabel(&quot;&quot;) layout.addWidget(progress_label) def report_progress(value): progress_label.setText(f&quot;{value}% Complete&quot;) def finish_task(): global worker_thread if worker_thread.isRunning(): worker_thread.quit() # Ensure proper cleanup after completion. button.setEnabled(True) QMessageBox.information(window, &quot;&quot;, &quot;Compilation Finished!&quot;) button.clicked.connect(start_task) window.setLayout(layout) window.show() sys.exit(app.exec_()) ``` 此脚本创建了一个小型桌面程序,在其中单击按钮即可触发后台线程执行 LuaLaTeX 编译工作流而不影响用户体验流畅度[^4]。 --- #### 总结 以上介绍了三种主要途径帮助开发者们解决有关于如何把 LuaLaTeX 整合进他们的项目中的疑问。无论是直接调用还是间接依赖其他框架辅助完成任务都各有优劣之处需视具体情况而定择取合适方案加以应用实践验证效果最佳者为之选型依据之一也即如此这般而已矣乎哉焉耳!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值