Org mode is for keeping notes, maintaining TODO lists, planning projects, and authoring documents with a fast and effective plain-text system.
Org-mode
類似于 Markdown
, 但是遠勝于 Markdown
趁冈。 曾有小伙伴說過, Org-mode
是 Markdown
的封神模式, 個人覺得這話一點不夸張, 相比較而言, Markdown
只是一套簡潔的文檔格式吭净, 而 Org-mode
除了涵蓋作為文檔格式的簡潔之外, 還可用于記筆記,維護 TODO 列表坯辩, 工程管理,以及可用于元編程。 對于元編程的支持請閱讀我之前的譯文崩侠, Babel: org-mode的元編程漆魔。
所謂的元編程,即是 Org-mode
搭建了一個多語言可以交互執(zhí)行的環(huán)境却音, 在這個環(huán)境中改抡,可選用各語言的特性,來分解執(zhí)行一個大型任務(wù)系瓢。
Org-mode
對于比較流行的語言都有很好的支持阿纤, 而且對于新語言,也可以很容易添加支持夷陋,本人就給兩種語言添加過支持欠拾。 本文章主要講述 Org-mode
對于 Python
源代碼塊的支持, Python
相當?shù)牧餍? 所以在 Org-mode
中被很完美的支持。 Org-mode
中的 Python
源代碼塊可用于定義函數(shù)骗绕、過濾器和數(shù)據(jù)分析藐窄、創(chuàng)建圖表以及生成可重現(xiàn)的研究論文。
配置
這里假設(shè) Python
的開發(fā)環(huán)境已配置完畢酬土,若是還沒配置枷邪,請自行g(shù)oogle。
Org-mode
已內(nèi)置在新的 Emacs 中,但是默認情況下东揣, 只有 emacs-lisp
可被執(zhí)行践惑。 要啟用或禁用其他語言, 可通過 Emacs 自定義交互界面來配置 org-babel-load-languages
變量, 或者將代碼添加到 init
文件中, 啟用python的代碼如下所示:
(org-babel-do-load-languages
'org-babel-load-languages
'((python . t)))
Org-mode對于Python源碼塊的支持
頭參數(shù)
語言特定的頭參數(shù)
- :results {output, value}: 默認
value
模式, 即 functional mode, 像函數(shù)一樣執(zhí)行,然后返回計算結(jié)果嘶卧。 - :preamble: 前導(dǎo)代碼尔觉,插入到最前面(不常用)。 默認為空芥吟。
- :return: 要返回的值(僅用于result-type為
value
時侦铜,不在session
模式下;不常用)。 默認值為空钟鸵,在Non-session
模式下钉稍,使用return()
返回值。 - :python: 執(zhí)行Python代碼的程序名稱棺耍。
公共頭參數(shù)
- :seesion [name]: 默認非
session
模式贡未。 - :var data=data-table:
Org-mode
的table
可被當做列表傳遞給Python代碼塊。 - :exports {code, results, both, none}: 完全支持
babel
的導(dǎo)出選項蒙袍。
Sessions
python完全支持 session
模式俊卤,包括命名 session
。 在 session
模式下害幅,代碼塊都運行在同一個長時間運行的 python
的交互式解釋器 session
中消恍,就像你在交互式 python
鍵入的一樣。 可以擁有多個 session
以现,而且它們是完全相互獨立狠怨。
session
可用于定義函數(shù),設(shè)置變量和在源塊之間共享代碼邑遏。
python中的 session
模式與 non-session
模式略有不同取董,因為在 session
模式下, 你正在與單個“交互式” python session
交互无宿。 在 python
的交互模式中,空行是特殊的:它們表示縮進代碼塊的結(jié)束, 所以會寫出一些稍微不同的 python
代碼枢里。
另外孽鸡,在 non-session
模式下,python代碼塊將被包裝在一個函數(shù)中栏豺, 所以要返回一個值( :result value mode
)彬碱,你必須使用一個return語句。 在 session
模式下奥洼, python
代碼由解釋器直接評估巷疼,而不是在一個函數(shù)的上下文中, 最后一個語句的值將被自動返回灵奖,因此不能使用 return
語句嚼沿。
Session mode
# blank lines not OK in indented blocks, and don't use return()
# Source block is passed directly to interactive python;
# value is value of _ at end.
#+begin_src python :session
def foo(x):
if x>0:
return x+1
else:
return x-1
foo(1)
#+end_src
#+RESULTS:
: 2
Non-session mode
# blank lines OK in indented blocks, and use return()
# Entire source block will get indented and used as the body of main()
#+begin_src python
def foo(x):
if x>0:
return x+1
else:
return x-1
return foo(5)
#+end_src
#+RESULTS:
: 6
最后估盘,如果你使用 matplotlib
的圖形功能,同時使用 seesion
模式骡尽, 必須顯式設(shè)置后端, 例如 PDF , PNG 或其他文件導(dǎo)出后端遣妥。 見下面示例:
#+begin_src python :session :results file
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt
fig=plt.figure(figsize=(3,2))
plt.plot([1,3,2])
fig.tight_layout()
plt.savefig('images/myfig.pdf')
'images/myfig.pdf' # return this to org-mode
#+end_src
#+RESULTS:
[[file:images/myfig.pdf]]
返回類型
- value:=value= 結(jié)果是代碼塊中求值的最后一個表達式的值。
session
模式下使用的python解釋器特殊變量“_” 來引用最后一個表達式的值攀细。 - output:=output= 結(jié)果來自
python
代碼打印到stdout
上任意信息箫踩。
示例
-
Hello World!
#+begin_src python :results output print "Hello, world!" #+end_src #+RESULTS: : Hello, world!
-
參數(shù)
#+NAME: square #+BEGIN_SRC python :var num=5 def square(x): return x*x return square(num) #+END_SRC #+RESULTS: square : 25 #+CALL: square(num=10) #+RESULTS: : 100
文學(xué)編程
#+NAME: square
#+BEGIN_SRC python
def square(x):
return x*x
#+END_SRC
#+NAME: calc-square
#+BEGIN_SRC python :var num=5 :noweb strip-export :results output
<<square>>
print(square(num))
#+END_SRC
#+RESULTS: calc-square
: 25
#+CALL: calc-square(num=7)
#+RESULTS:
: 49
-
內(nèi)聯(lián)調(diào)用(Inline calling):
2 加 2 等于 src_python{return(2+2)}
當導(dǎo)出 HTML 或者 LaTeX/PDF 時,如下所示:
2 加 2 等于 4
-
使用Org-mode的table作為參數(shù)
#+tblname: data_table | a | 1 | | b | 2 | | c | 3 | #+begin_src python :var val=1 :var data=data_table # Return row specified by val. # In non-session mode, use return to return results. return(data[val]) #+end_src #+RESULTS: | b | 2 |
-
繪圖
#+begin_src python :results file import matplotlib, numpy matplotlib.use('Agg') import matplotlib.pyplot as plt fig=plt.figure(figsize=(4,2)) x=numpy.linspace(-15,15) plt.plot(numpy.sin(x)/x) fig.tight_layout() plt.savefig('../images/python-matplot-fig.png') return '../images/python-matplot-fig.png' #+end_src #+RESULTS: [[file:../images/python-matplot-fig.png]]
- 詞云
#+BEGIN_SRC python :preamble "# -*- coding: utf-8 -*-" :results value file
import jieba.analyse
from wordcloud import WordCloud, ImageColorGenerator
import numpy as np
from PIL import Image
import random
font_path = '../resource/tyzkaishu.ttf'
width = 640
height = 480
text = open('../resource/xiyouji.txt').read()
words = jieba.analyse.extract_tags(text, topK=200, withWeight=True)
word_freqs = {}
for word in words:
word_freqs[word[0]] = word[1]
mask = np.array(Image.open('../resource/stormtrooper_mask.png'))
wordcloud = WordCloud(
font_path=font_path, width=width, height=height,
mask=mask).generate_from_frequencies(word_freqs)
wordcloud.to_file('../images/xiyouji-mask.png')
return '../images/xiyouji-mask.png'
#+END_SRC
#+RESULTS:
[[file:../images/xiyouji-mask.png]]
前方預(yù)警
當把 utf-8
的字符串傳給 Python
, 需要格外小心谭贪。
傳遞utf-8字符串到Python
#+NAME: unicode_str
#+BEGIN_EXAMPLE
“this string is not ascii!”
#+END_EXAMPLE
#+NAME: error-in-passing-var
#+BEGIN_SRC python :var data=unicode_str
return data
#+END_SRC
#+RESULTS: error-in-passing-var
上面代碼不會生成任何輸出, 并在 *Org-Babel Error Output*
的緩沖區(qū)中打印以下消息:
File “<stdin>”, line 3 SyntaxError: Non-ASCII character ’\xe2’ in file <stdin> on line 3, but no encoding declared; see http://python.org/dev/peps/pep-0263/ for details
傳遞utf-8字符串到Python的變通方法
一個變通方法是使用 :preamble
,如下所示:
#+NAME: ok-in-passing-var
#+BEGIN_SRC python :preamble "# -*- coding: utf-8 -*-" :var data=unicode_str
return data
#+END_SRC
#+RESULTS: ok-in-passing-var
: “this string is not ascii!”