Community程式設計與開發github.com

pwquint24/org-babel-notebook

使用 Org Babel 在 Emacs Org Mode 中編寫、組織、執行和發布互動式計算筆記本的完整指南。

org-babel-notebook 是什麼?

這項技能提供了一份全面的指南,指導開發者如何利用 Org Babel 將 Emacs Org Mode 轉變為一個強大的互動式、多語言計算筆記本環境。與 Jupyter 或 Mathematica 類似,Org Babel 允許您在單一文件中交織執行代碼、嵌入即時結果、顯示圖表、繪製圖形以及書寫敘述性文字。不同於 JSON 格式的筆記本,Org 文件是純文字,具有人類可讀性,天生支援 Git 版本控制,並且可以在同一個文件中混合使用多種程式語言。 該技能詳細說明了 Org Babel 的核心架構,特別是透過五種不同的標頭參數(`:session`、`:results`、`:exports`、`:tangle`、`:var`)來明確分離執行、結果、匯出、程式碼萃取與組合等關注點,這對於避免常見錯誤至關重要。它提供了完整的筆記本前置設定範本,指導如何設定緩衝區範圍的預設值、啟用多種程式語言(如 Python、R、Shell、SQLite 等),並深入解釋了程式碼區塊的語法結構。 進一步地,本指南深入探討了結果處理的核心區別,即 `:results value`(函數式,擷取回傳值)與 `:results output`(腳本式,擷取標準輸出)的差異,這解決了 Org Babel 中 90% 的混淆問題。它也涵蓋了透過 `:session` 進行互動式探索與可重複性研究的權衡,以及使用 `:cache` 快取昂貴計算、透過 `:dir` 管理工作目錄、甚至利用 TRAMP 進行遠端執行等高階主題。 最後,這項技能還包含了生成可內嵌顯示的視覺化圖表(如 Matplotlib 與 ggplot2)的完整範例、互動式執行與編輯的按鍵綁定、將筆記本匯出為 HTML 或 PDF 報告的方法,以及一個常見問題排錯檢查表。整體而言,它是一個將科學計算、資料分析與文件撰寫完美整合在 Emacs 中的終極參考資源。

相容平台~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/pwquint24/org-babel-agent-skills/tree/HEAD/skills/org-babel-notebook

Installed? Explore more 程式設計與開發 skills: steipete/bluebubbles, steipete/eightctl, steipete/blucli · View all 6 →

在你喜歡的 AI 中提問

開啟一個已預先載入此 Agent Skill 的新對話。

說明文件

使用 Org Babel 編寫計算筆記本

Org Babel 將 Emacs Org Mode 轉變為一個互動式的多語言計算筆記本環境。與 Jupyter 或 Mathematica 類似,Org Babel 交織了可執行代碼、即時執行結果、圖形、表格和敘述性文字。不同於基於 JSON 的筆記本,Org 筆記本是純文字、人類可讀、原生支援 Git 版本控制,並且允許在單一文件中混合使用多種程式語言。


1. 核心架構與關注點分離

每個 Org Babel 筆記本都透過標頭參數在五個不同的關注點上運作。混淆這些是 Org 筆記本中錯誤的主要來源:

關注點關鍵標頭參數控制內容
執行:session, :eval, :dir, :var, :cache程式區塊是否執行、在哪個程序中執行、在何處執行以及使用什麼輸入?
結果:results (value vs output, 格式, 類型, 處理方式)從執行中捕獲了什麼,以及如何在緩衝區中呈現?
匯出:exports (code, results, both, none)匯出的報告(HTML, PDF, Markdown)中會出現什麼?
萃取:tangle, :shebang, :noweb哪些內容會被提取到磁碟上的獨立原始碼檔案?
組合:var, #+CALL:, <<noweb>>, org-sbe區塊如何相互饋送資料或程式碼?

2. 筆記本結構與前置設定

Org 筆記本檔案 (.org) 以文件元資料和緩衝區範圍的預設設定開始,接著是包含敘述文字、數學公式和程式碼區塊的分層標題。

2.1 標準筆記本前置設定範本

#+TITLE: Computational Analysis of Experiment X
#+AUTHOR: Jane Doe
#+DATE: [2025-05-18 Sun]
#+OPTIONS: toc:2 num:t ^:{}
#+STARTUP: overview hideblocks inlineimages

# 此緩衝區中所有區塊的全域 Babel 預設值:
#+PROPERTY: header-args :eval yes :exports both :results drawer
# 語言特定的預設值:
#+PROPERTY: header-args:python :session *py-analysis* :results value :exports both
#+PROPERTY: header-args:R :session *R-analysis* :results value :exports both
#+PROPERTY: header-args:sh :session none :results output :exports both

關鍵的緩衝區內設定:

  • #+STARTUP: inlineimages:當插入結果或開啟緩衝區時,自動顯示生成的圖表/圖片。
  • #+STARTUP: hideblocks:開始時摺疊程式碼區塊,僅顯示敘述和結果以提高可讀性。
  • #+STARTUP: nohideblocks:顯示所有已展開的程式碼區塊。
  • #+PROPERTY: header-args ...:緩衝區範圍的預設值。可以使用 header-args+ 追加。

2.2 在 Emacs 設定中啟用語言

Org 預設僅啟用 Emacs Lisp 評估。所有其他語言必須在您的 Emacs 設定中明確載入:

(org-babel-do-load-languages
 'org-babel-load-languages
 '((emacs-lisp . t)
   (python     . t)
   (R          . t)
   (shell      . t)
   (sqlite     . t)
   (gnuplot    . t)
   (C          . t)))

為了避免對受信任的筆記本出現互動式執行確認對話框:

;; nil 允許區塊在沒有確認提示的情況下執行
(setq org-confirm-babel-evaluate nil)

3. 程式碼區塊結構

#+NAME: <block_name>
#+HEADER: <additional_header_args>
#+BEGIN_SRC <language> <switches> <header_arguments>
  <body>
#+END_SRC
  • #+NAME: <name>:可選的唯一標識符。如果該區塊將被作為函數引用、作為輸入透過 :var 傳遞給另一個區塊,或透過 #+CALL: 調用,則此項為必填。
  • <language>:Babel 識別的標識符(python, R, sh, emacs-lisp, sqlite, sql, julia, calc, gnuplot 等)。
  • <switches>:可選的開關(例如,匯出時的行號 -n,用於移除標籤的 -r)。
  • <header_arguments>:控制執行、結果和匯出的鍵值對。
  • #+HEADER::用於整潔地指定長列表標頭參數的輔助行。

內聯程式碼區塊

為了在段落內嵌入動態計算值:

The final computed accuracy was src_python[:session *py* :results value]{f"{acc * 100:.2f}%"}.

4. 標頭參數參考

4.1 會話管理:互動式探索 vs 封閉式可重複性

  • :session none(預設):在一次性外部解釋器進程中評估區塊。封閉、乾淨且避免狀態污染,但每次運行時都會重新初始化導入和環境。
  • :session <name>:在持久的 Emacs inferior REPL 緩衝區(例如 *py-analysis*)中評估。
    • 變數、函數和導入的模組在共享相同會話名稱的多個區塊之間持續存在。
    • 對於大型資料集、大型模型權重和探索性工作流程至關重要。
    • 最佳實踐: 使用 :session <name> 進行原型設計;對於最終驗證,重啟會話或使用 :session none 測試關鍵部分以保證可重複性。

4.2 工作目錄與遠端環境

  • :dir /path/to/project:在指定的目錄內運行區塊。
  • :mkdirp yes:如果目標目錄不存在,則創建它。
  • 遠端執行 (TRAMP): :dir /ssh:user@gpu-cluster:/workspace/data 在伺服器上遠端執行區塊,同時在您的本地 Emacs 緩衝區中呈現輸出。

4.3 快取昂貴的計算

  • :cache yes:計算區塊文字、輸入和 :var 參數的 SHA1 雜湊值。
  • 如果雜湊值與存儲在 #+RESULTS[hash]: 行上的值匹配,則跳過評估並保留快取的結果。
  • 僅用於確定性的、無外部副作用的純計算。

5. 結果處理:關鍵區別

:results 參數最多接受四個正交組件:

:results [collection] [type] [format] [handling]

5.1 收集模式:函數式 (value) vs 腳本式 (output)

理解這個差異可以消除 90% 的 Babel 混淆:

收集模式捕獲內容Python 行為Shell 行為
:results value(Python, R, elisp 的預設值)最終表達式的 回傳值 或顯式 return。必須使用顯式的 return <val> 語句。所有 print() 輸出都會被 丟棄。回傳退出碼或字串值。
:results output(shell, bash 的預設值)執行期間發出的 標準輸出流。捕獲所有 print() 語句。任何 return 都會被忽略。捕獲所有命令的標準輸出(echo, ls 等)。

Python 函數式範例 (:results value):

#+BEGIN_SRC python :results value
  data = [1, 2, 3, 4]
  # 在函數模式下,Python 中需要顯式回傳:
  return sum(data)
#+END_SRC

#+RESULTS:
: 10

Python 腳本式範例 (:results output):

#+BEGIN_SRC python :results output
  for i in range(3):
      print(f"Epoch {i}: loss={0.5/(i+1):.4f}")
#+END_SRC

#+RESULTS:
: Epoch 0: loss=0.5000
: Epoch 1: loss=0.2500
: Epoch 2: loss=0.1667

5.2 結果類型

  • table / vector:將回傳的列表/陣列格式化為 Org Mode 表格。
  • scalar / verbatim:將輸出格式化為原始引文文字,不進行表格格式化。
  • file:將輸出導向到磁碟上的檔案(使用 :file <filename> 指定),並將 Org 檔案連結插入到結果中。

5.3 結果格式

  • drawer(推薦):將結果包裹在 :RESULTS: … :END: 分隔符中。保持文檔整潔,特別適用於多行輸出。
  • raw:直接插入輸出作為未轉義的 Org 文字(用於生成動態標題或表格很有用)。
  • code:將輸出包裹在 #+BEGIN_SRC <lang> … #+END_SRC 中。
  • link / graphics:將結果視為圖片/檔案的路徑,並生成 [[file:path]]。

5.4 處理方式

  • replace(預設):替換先前的 #+RESULTS: 區塊。
  • append:在現有結果下方附加新結果。
  • prepend:在現有結果上方插入新結果。
  • silent:在 Emacs 回顯區/迷你緩衝區中顯示結果,而不寫入 Org 緩衝區。

6. 筆記本中的視覺化與圖形

要生成直接在筆記本中呈現的圖形和圖表:

6.1 Python Matplotlib 圖表

#+NAME: plot-normal-distribution
#+BEGIN_SRC python :session *py-vis* :results graphics file :file figures/normal_dist.png :exports both
  import matplotlib.pyplot as plt
  import numpy as np

  plt.figure(figsize=(6, 3.5))
  x = np.linspace(-3, 3, 200)
  plt.plot(x, np.exp(-x**2 / 2) / np.sqrt(2 * np.pi), color="#2b5c8f", lw=2)
  plt.title("Standard Normal Distribution")
  plt.xlabel("z")
  plt.ylabel("Density")
  plt.tight_layout()
  plt.savefig("figures/normal_dist.png", dpi=150)
  plt.close()
#+END_SRC

#+RESULTS: plot-normal-distribution
[[file:figures/normal_dist.png]]

6.2 R ggplot2 圖表

#+NAME: r-scatter-plot
#+BEGIN_SRC R :session *r-vis* :results graphics file :file figures/r_scatter.png :exports both
  library(ggplot2)
  p <- ggplot(mtcars, aes(x=wt, y=mpg, color=factor(cyl))) +
    geom_point(size=3) +
    theme_minimal() +
    labs(title="Fuel Efficiency vs Weight", x="Weight (1000 lbs)", y="MPG")
  ggsave("figures/r_scatter.png", plot=p, width=6, height=4, dpi=150)
#+END_SRC

#+RESULTS: r-scatter-plot
[[file:figures/r_scatter.png]]

提示: 在 Emacs 中運行 M-x org-toggle-inline-images (C-c C-x C-v) 來切換在緩衝區內顯示生成的圖形。


7. 互動式執行與編輯工作流程

基本按鍵綁定

按鍵綁定命令描述
C-c C-corg-babel-execute-src-block執行游標下的區塊並插入/更新結果。
C-c 'org-edit-special在專用的主模式緩衝區中開啟區塊主體(完整的 LSP、語法高亮、自動補全)。再次按 C-c ' 儲存並返回。
C-c C-v borg-babel-execute-buffer依序執行筆記本中的 所有 程式碼區塊(類似「運行所有儲存格」)。
C-c C-v sorg-babel-execute-subtree執行當前標題下的所有程式碼區塊。
C-c C-oorg-open-at-point在 #+RESULTS: 連結上時,在外部檢視器或緩衝區中開啟圖片或生成的檔案。
M-<down>org-babel-pop-to-session將焦點直接切換到此區塊會話的互動式 REPL 緩衝區。
C-c C-v vorg-babel-expand-src-block預覽完全展開的區塊(所有 :var 和 noweb 展開已解析)。

8. 匯出與發布報告

筆記本可以被編織成獨立的 HTML、PDF 或 Markdown 文件。

8.1 使用 :exports 控制匯出內容

  • :exports code:僅匯出程式碼區塊。
  • :exports results:僅匯出輸出/圖形(隱藏程式碼,非常適合執行摘要報告)。
  • :exports both:同時匯出程式碼和輸出(非常適合技術文件)。
  • :exports none:從匯出的文件中隱藏程式碼和結果(如果需要,在評估期間仍會執行)。

8.2 使用 :eval 控制匯出評估

  • :eval never-export:防止在匯出期間重新運行區塊,使用緩衝區中現有的 #+RESULTS:。加快匯出速度並防止非確定性更改。
  • :eval query-export:在匯出期間執行前提示。

8.3 匯出命令

  • C-c C-e h h (org-html-export-to-html):生成 HTML 報告。
  • C-c C-e h o (org-html-export-to-html-and-open):生成並在瀏覽器中開啟 HTML。
  • C-c C-e l p (org-latex-export-to-pdf):透過 LaTeX 生成排版精美的 PDF 報告。

9. 常見陷阱與故障排除檢查表

症狀 / 錯誤原因修正
Python 區塊沒有回傳結果使用了 :results value 但使用了 print(...) 而不是 return ...將 print(...) 替換為 return ...,或將標頭更改為 :results output。
No org-babel-execute function for <lang>語言未在 org-babel-load-languages 中註冊在您的 Emacs 設定中將 (<lang> . t) 添加到 org-babel-load-languages 並評估它。
產生了圖片連結但圖片未顯示Org Mode 中內聯圖片顯示已關閉運行 M-x org-toggle-inline-images (C-c C-x C-v) 或添加 #+STARTUP: inlineimages。
會話輸出包含重複提示 (>>>)REPL 緩衝區中殘留的互動式提示文字清理或重啟會話緩衝區 (*session-name*)。
匯出緩慢或卡住Org 在匯出期間重新執行所有筆記本區塊在長時間運行的區塊上設定 :eval never-export,或透過 #+PROPERTY: header-args :eval never-export 全域設定。
表格輸入在水平規則上產生錯誤水平規則 (`-`) 被視為原始行

10. 完整註解的筆記本範例

#+TITLE: Solar Flare Frequency Analysis
#+AUTHOR: Dr. Alex Rivera
#+DATE: [2025-05-18 Sun]
#+OPTIONS: toc:nil num:nil
#+STARTUP: inlineimages nohideblocks
#+PROPERTY: header-args :session *solar* :results drawer :exports both

* Introduction
我們分析了在一個 6 個月的觀測窗口內記錄的觀測耀斑頻率。

* Raw Observations
這是基線測量表格:

#+NAME: raw_observations
| Month | C-Class | M-Class | X-Class |
|-------+---------+---------+---------|
| Jan   |      12 |       3 |       0 |
| Feb   |      19 |       5 |       1 |
| Mar   |      15 |       2 |       0 |
| Apr   |      27 |       8 |       2 |
| May   |      31 |      11 |       3 |
| Jun   |      22 |       7 |       1 |

* Data Processing & Summary Statistics
我們使用 Python 計算總的太陽活動量:

#+NAME: compute_totals
#+BEGIN_SRC python :var obs=raw_observations :colnames yes :results value table
  total_events = []
  for row in obs:
      month = row[0]
      total = sum(row[1:])
      total_events.append([month, total])
  return [["Month", "Total Events"]] + total_events
#+END_SRC

#+RESULTS: compute_totals
:RESULTS:
| Month | Total Events |
|-------+--------------|
| Jan   |           15 |
| Feb   |           25 |
| Mar   |           17 |
| Apr   |           37 |
| May   |           45 |
| Jun   |           30 |
:END:

* Visualization
每月總事件數的長條圖:

#+NAME: flare_bar_chart
#+BEGIN_SRC python :session *solar* :results graphics file :file figures/flare_totals.png :exports both
  import matplotlib.pyplot as plt
  import numpy as np

  months = ["Jan", "Feb", "Mar", "Apr", "May", "Jun"]
  totals = [15, 25, 17, 37, 45, 30]

  plt.figure(figsize=(6, 4))
  plt.bar(months, totals, color="#2b5c8f")
  plt.title("Total Solar Flare Events by Month")
  plt.xlabel("Month")
  plt.ylabel("Total Events")
  plt.tight_layout()
  plt.savefig("figures/flare_totals.png", dpi=150)
  plt.close()
#+END_SRC

#+RESULTS: flare_bar_chart
[[file:figures/flare_totals.png]]

* Conclusion
數據顯示在所觀測的期間內,太陽活動從 1 月到 5 月呈上升趨勢,並在 6 月略有下降。

Individual skills in this repo

This repo contains 4 individual skills — each has its own dedicated page.

相關技能