寫Python的新方式

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-modeMarkdown 的封神模式, 個人覺得這話一點不夸張, 相比較而言, Markdown 只是一套簡潔的文檔格式, 而 Org-mode 除了涵蓋作為文檔格式的簡潔之外, 還可用于記筆記,維護 TODO 列表, 工程管理,以及可用于元編程。 對于元編程的支持請閱讀我之前的譯文, Babel: org-mode的元編程

所謂的元編程,即是 Org-mode 搭建了一個多語言可以交互執行的環境, 在這個環境中,可選用各語言的特性,來分解執行一個大型任務。

Org-mode 對于比較流行的語言都有很好的支持, 而且對于新語言,也可以很容易添加支持,本人就給兩種語言添加過支持。 本文章主要講述 Org-mode 對于 Python 源代碼塊的支持, Python 相當的流行, 所以在 Org-mode 中被很完美的支持。 Org-mode 中的 Python 源代碼塊可用于定義函數、過濾器和數據分析、創建圖表以及生成可重現的研究論文。

配置

這里假設 Python 的開發環境已配置完畢,若是還沒配置,請自行google。

Org-mode 已內置在新的 Emacs 中,但是默認情況下, 只有 emacs-lisp 可被執行。 要啟用或禁用其他語言, 可通過 Emacs 自定義交互界面來配置 org-babel-load-languages 變量, 或者將代碼添加到 init 文件中, 啟用python的代碼如下所示:

(org-babel-do-load-languages
 'org-babel-load-languages
 '((python . t)))

Org-mode對于Python源碼塊的支持

頭參數

語言特定的頭參數

  • :results {output, value}: 默認 value 模式, 即 functional mode, 像函數一樣執行,然后返回計算結果。
  • :preamble: 前導代碼,插入到最前面(不常用)。 默認為空。
  • :return: 要返回的值(僅用于result-type為 value 時,不在 session 模式下;不常用)。 默認值為空,在 Non-session 模式下,使用 return() 返回值。
  • :python: 執行Python代碼的程序名稱。

公共頭參數

  • :seesion [name]: 默認非 session 模式。
  • :var data=data-table: Org-modetable 可被當做列表傳遞給Python代碼塊。
  • :exports {code, results, both, none}: 完全支持 babel 的導出選項。

Sessions

python完全支持 session 模式,包括命名 session 。 在 session 模式下,代碼塊都運行在同一個長時間運行的 python 的交互式解釋器 session 中,就像你在交互式 python 鍵入的一樣。 可以擁有多個 session ,而且它們是完全相互獨立。

session 可用于定義函數,設置變量和在源塊之間共享代碼。

python中的 session 模式與 non-session 模式略有不同,因為在 session 模式下, 你正在與單個“交互式” python session 交互。 在 python 的交互模式中,空行是特殊的:它們表示縮進代碼塊的結束, 所以會寫出一些稍微不同的 python 代碼。

另外,在 non-session 模式下,python代碼塊將被包裝在一個函數中, 所以要返回一個值( :result value mode ),你必須使用一個return語句。 在 session 模式下, python 代碼由解釋器直接評估,而不是在一個函數的上下文中, 最后一個語句的值將被自動返回,因此不能使用 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 模式, 必須顯式設置后端, 例如 PDF , PNG 或其他文件導出后端。 見下面示例:

#+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= 結果是代碼塊中求值的最后一個表達式的值。 session 模式下使用的python解釋器特殊變量“_” 來引用最后一個表達式的值。
  • output:=output= 結果來自 python 代碼打印到 stdout 上任意信息。

示例

  • Hello World!

    #+begin_src python :results output
      print "Hello, world!"
    #+end_src
    
    #+RESULTS:
    : Hello, world!
    
  • 參數

    #+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
    
  • 文學編程

    #+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
  • 內聯調用(Inline calling):

    2 加 2 等于 src_python{return(2+2)}
    

    當導出 HTML 或者 LaTeX/PDF 時,如下所示:

    2 加 2 等于 4
    
  • 使用Org-mode的table作為參數

    #+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]]
    
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]]
xiyouji-mask.png

前方預警

當把 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* 的緩沖區中打印以下消息:

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!”

參考文檔

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,563評論 6 544
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,694評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,672評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,965評論 1 318
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,690評論 6 413
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 56,019評論 1 329
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 44,013評論 3 449
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 43,188評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,718評論 1 336
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,438評論 3 360
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,667評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,149評論 5 365
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,845評論 3 351
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,252評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,590評論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,384評論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,635評論 2 380

推薦閱讀更多精彩內容