16.5 Evaluating Code Blocks

安全提示:执行代码存在安全风险。Org 提供保护机制,执行任何代码前都会请求用户授权。自定义或关闭该保护机制见 Code Evaluation and Security Issues

How to evaluate source code

Org 会捕获代码块执行结果,并插入到 Org 文件中代码块的后方,位置在换行与 ‘RESULTS’ 关键字之后。若不存在 ‘RESULTS’ 关键字则自动创建。详细说明见 Results of Evaluation

默认仅启用 Emacs Lisp 代码块执行,启用其他语言见 Languages

Org 提供多种执行代码块的方式。将光标定位在代码块上按下 C-c C-cC-c C-v e 155 会调用 org-babel-execute-src-block 函数,执行代码、收集结果并插入缓冲区。

可在 Org 缓冲区或表格中调用命名代码块156,支持调用当前文件或「Babel 库」(见 Library of Babel)中的命名块。

CALL’ 关键字语法:

#+CALL: <name>(<arguments>)
#+CALL: <name>[<inside header arguments>](<arguments>) <end header arguments>

行内命名代码块语法:

... call_<name>(<arguments>) ...
... call_<name>[<inside header arguments>](<arguments>)[<end header arguments>] ...

使用行内语法时,结果会根据变量 org-babel-inline-result-wrap 包装,默认值为 "=%s=" ,生成适合标记的原样文本。

<name>

待执行的当前文档内代码块名称(见 Structure of Code Blocks)。若块位于其他文件, ‘<name>’ 以文件名加冒号开头。例如执行 ‘file.org’ 中名为 ‘clear-data’ 的块:

#+CALL: file.org:clear-data()
<arguments>

Org 使用标准函数调用语法向代码块传递参数。例如,在 ‘#+CALL:’ 行中将 ‘4’ 传递给名为 ‘double’ 、且声明了头部参数 ‘:var n=2’ 的代码块,写法如下:

#+CALL: double(n=4)

注意该函数调用语法与头部参数语法的区别。

<inside header arguments>

Org 使用头部参数语法向已命名的代码块传递内部头部参数。内部头部参数作用于代码块的执行过程。例如, ‘[:results output]’ 会收集该代码块执行期间输出到标准输出的结果。注意该头部参数语法与函数调用语法的区别。

<end header arguments>

尾部头部参数会影响代码块返回的结果。例如, ‘:results html’ 会在将结果插入到 Org 缓冲区之前,把结果包裹在 ‘#+BEGIN_EXPORT html’ 块中。

Limit code block evaluation

eval’ 头部参数可限制特定代码块与 ‘CALL’ 关键字的执行,用于防范不受信任代码,可设置为执行前确认。

yes

Org 执行源代码,是否询问权限由 org-confirm-babel-evaluate 决定。

never’ or ‘no

永不执行源代码。

query

每次执行前均询问用户权限。

never-export’ 或 ‘no-export

导出时不执行,但用户可交互式执行。

query-export

导出时询问用户是否执行。

若未设置 ‘eval’ ,是否执行由 org-confirm-babel-evaluate 变量决定(见 Code Evaluation and Security Issues)。

Cache results of evaluation

cache’ 头部参数用于缓存代码块执行结果,避免重复执行未修改的代码块。使用缓存需满足:缓冲区中已有结果,且头部参数(含 ‘var’ 引用值)与代码块内容自上次计算后未变更。该功能可大幅减少耗时计算,但部分极端场景下缓存结果可能不可靠。

缓存功能最适合纯函数代码块:相同输入始终返回相同结果(见 Environment of a Code Block)、无副作用、不依赖输入以外的外部变量。依赖计时器、文件系统、随机数的函数不适合缓存。

警告:在会话中使用 ‘cache’ 可能产生意外结果。

缓存机制检测代码变更时,不会展开 noweb 引用(见 Noweb Reference Syntax)。

cache’ 可取 ‘yes’ 或 ‘no’ :

no

默认值。不缓存结果,每次均重新执行。

yes

是否运行代码或返回缓存结果,取决于对代码块整体及其传入参数组合后的 SHA1 哈希值进行比对。该哈希值会在之前执行后记录在 ‘#+RESULTS:’ 行中。当哈希值匹配时,Org 不会执行该代码块;当哈希值不匹配时,Org 会执行代码块、插入结果、重新计算哈希值并更新 ‘#+RESULTS:’ 行。

在本示例中,两个函数均会被缓存。但只有 ‘random’ 的结果与上次运行相比发生变化时,=caller= 才会执行。

#+NAME: random
#+BEGIN_SRC R :cache yes
  runif(+1)
#+END_SRC

#+RESULTS[a2a72cd647ad44515fab62e144796432793d68e1]: random
0.4659510825295

#+NAME: caller
#+BEGIN_SRC emacs-lisp :var x=random :cache yes
  x
#+END_SRC

#+RESULTS[bec9c8724e397d5df3b696502df3ed7892fc4f5f]: caller
0.254227238707244

Footnotes

(155)

可通过选项 org-babel-no-eval-on-ctrl-c-ctrl-c 移除 C-c C-c 的代码执行功能。

(156)

实际上, ‘call_<name>()’ 与 ‘src_<lang>{}’ 出现在关键字中时不会被执行,参见 Summary of In-Buffer Settings