关于 org 的 :session 和 :noweb 的思考

我觉得两种的使用场合不同,并不能简单的认为哪一种更优越。

对于 :session 模式,它的作用主要是始终可以访问同一个 :session,这样的话你随时可以 访问指定 :session 中的变量。比如下列代码:

#+begin_src ipython :session mysession
import numpy as np
var = np.pi * 2
#+end_src

这样,下次如果需要访问这个变量 var 的时候,不需要重新启动一个进程,而只需要指定 var 所在的 session 就可以了:

#+begin_src ipython :session mysession
print var
#+end_src

这实际上提供了类似于 ipython notebook 的功能,这对于交互式计算非常有帮助。特别是当你前面的运算非常耗时的时候,你不会希望每次都从头开始。

另一方面, 当使用 :noweb 而不是 :session 的时候,代码每次都是从头运行,这样的好处是 每次重新打开 buffer 后,不需要将前面的 src block 都运行一遍,但是缺点是:和单个 non session block 一样,每次运行完后即退出进程,下次会重新开始运行。

另外, :noweb 的用途不仅在 evaluate,还在于 tangle 以及 export 上。

综上,这两种有不同的使用情形,应该根据你的需要灵活选择。

欢迎大家加入讨论!

PS:我觉得论坛的 markup 貌似有点问题,因为上面的代码块结构相似,但是 highlight 的效果截然不同。

1 个赞

我倾向于 :noweb,大概是因为我的使用场景,并不涉及大量消耗资源的运算,相反,我更在意的是

  • block 的组合使用
  • 被引用的 block 修改之后立即生效,避免因忘记 C-c C-c 而产生的乌龙
  • 结果的一致性,每次都是从头开始,不会因为中间某个 block 执行了多次,导致结果超出预期

也许在代码补全方面,可以 hack 一下语言 mode,例如 python,把 <<bolck_name>> 当作 import 对待,会比较容易实现。

你使用了 Github Flavored Markdown Fenced Code Blocks 并且没有设置语言,于是论坛就会猜测你所用的是哪种语言,于是自然会有猜错的时候。你可以自己手动设置语言 python,或者用原生的 Code Block(行首 4 个空格)来避免高亮。

1 个赞

我有时会偷懒用 org-mode 来写测试(就是很多人都不愿意写的那种测试)。

把条件/需要复用的代码写在 block1, block2, …blockn。

然后写用例:

  • test1 引用 block1/3/5
  • test2 引用 block2/4/6
  • test3 引用 block1/2/3

这样每个 test 块的输出都是可预期的,不必担心那些前置的 block 已经运行过多少次/缓存了什么。


另,:session:noweb 并不相互排斥,完全可以共存:

#+BEGIN_SRC python :results silent :session
  import time
  import datetime

  def timestamp(str):
      ts = datetime.datetime.fromtimestamp(time.time()).strftime('%Y-%m-%d %H:%M:%S')
      return '[%s] %s' % (str, ts)

  session_ts = timestamp('session')
#+END_SRC

# ------------------------------------------------------------------

#+NAME: noweb_ts
#+BEGIN_SRC python :results none :noweb yes
  noweb_ts = timestamp('noweb')
#+END_SRC

# ------------------------------------------------------------------

#+BEGIN_SRC python :results output :session :noweb yes
  <<noweb_ts>>
  print(session_ts)
  print(noweb_ts)
#+END_SRC

#+RESULTS:
: [session] 2017-04-12 11:47:18
: [noweb] 2017-04-12 11:47:50

上边混用了两种块,session 的时间戳是固定的,noweb 每次都更新。

但是如果没有性能上的考量,我认为 :noweb 在使用上更轻松一些,不用每次修改后重新执行,可以更细致地控制块与块之间的引用和依赖。

1 个赞

完全同意, 但是我一般还是习惯 :session, :noweb 只是在 tangle 的时候用。org 的 babel 使用场景太灵活了,100 个人就有 100 种不同的用法,再加上各种 hack,简直了。。。所以用上手 babel 以后果断放弃 ipython notebook 了。