注釋:本文原來轉自部落格大巴的一篇文章,向原作者致謝!我也做了相應的修改,更加完善對於Pythonx,y的介紹
Python 二三事
面向初學者介紹Python相關的一些工具,以及可能遇到的常見問題。
更新1st 2011.1.15
更新2nd 2012.3.4
引言
在這裡我假設你已經看完了一篇Python教程,基本熟悉了Python的結構和文法,在命令列下的Python互動環境中嘗試過大部分Python的語句,覺得Python是個不錯的語言準備繼續下去。那麼本篇文章會就Python實際運用中相關工具的選擇,包括IDE,調試套件,第三方庫管理工具這些進行介紹。另外還會對某些中文環境下容易遇到的問題,例如unicode編碼解碼的問題進行說明。本文主要是針對 Windows 環境下的 Python 開發進行說明。文章的目的是為了分享些我覺得很有用的經驗和例子,若發現文中有疏漏之處請務必聯絡我。謝謝。
Python 語言介紹
Python 是一個近些年在開始流行起來的電腦程式設計語言。根據Python官網上的簡介,Python主要特性包括跨平台,免費,簡單且容易維護。就我個人理解來說,Python是一門適合大部分人的語言,因為各種類型的第三方庫都有,所以像簡單傳統型程式,動態網站開發,影像處理,表格處理,甚至自動發帖機這些小應用在簡單的學習後,不需要很深厚的編程經驗的人應該都能自己做出來。
一些流行的Python教程
Dive into Python 面向有一定編程基礎的同學。另外還有Dive into Python 3,針對Python3的教程。
Learn Python The Hard Way,書中主要是通過各種練習來進行學習,面向完全沒有編程經驗的同學。
Invent Your Own Computer Game With Python,讓你一上手就做個遊戲出來的教程,厲害吧。
The Python Tutorial,官方文檔中的教程,正統而完整。
How to think like a scientist:learn with Python,強烈推薦初學Python和編程的同學,MIT的教材,目前也被用於南科大的CS課程中
Hello,World 教小孩子學編程的好書,使用的是Python作為程式設計語言
如果你還沒有開始接觸 Python ,或者覺得還不夠熟悉,那麼不妨找一份你覺得看得下去的教程開始學習吧。就我個人經驗來說,Python 是我到目前為止覺得學的最划得來的一門語言,也是日常用的最多的一門,而事實上你並不需要瞭解完全瞭解 Python 就能在開始使用它。
Python 版本選擇,其他發行版糾結於Python 2 與 3?
Python 2 和 3 系列的選擇可能是比較讓人煩躁的事情。其實區別很簡單:Python 3.x 各個方面都更好,但文法與 Python 2.x 很大部分不相容。Python 2.x 已經停止繼續開發。但是目前很多第三方庫仍然不支援 Python 3 , 文章後面介紹的很多工具譬如 ipython 目前也是僅支援 Python 2.7 的。
我建議現在選擇 Python 2.7.2 ,因為目前大部分第三方庫和工具對2.7都有簡單的安裝包,不需要自己做太多處理,關於2.6還是2.7,推薦2.7,比2.6內建了一些包,不需要再安裝了。
發行版
目前在 Windows 下除了官方提供的安裝版外,還有:
ActivePython ,這個與官方版本的區別在於提供了額外的庫和文檔,並且自動化佈建了PATH環境變數(後文會詳細提到)
Python(x,y),這個是我一直用並且推薦給別人用的版本。從名字就能看出來這個發行版附帶了科學計算方面的很多常用庫,另外還有大量常用庫比如用於案頭軟體介面製作的 PyQt, 還有文檔處理,exe檔案產生等常用庫。另外的還有大量的工具如IDE,製圖製表工具,加強的互動shell之類。很多下文提到的軟體在此發行版中都有附帶。其他方面,Python(x, y)還附帶了手工整理出的所有庫的離線文檔,每個小版本升級都提供單獨的補丁。總的來說是很用心維護的一個發行版,十分建議安裝這個版本。
開發相關工具
在真正著手開發之前,你應該在下載一份離線的文檔。在這個頁面下載一份 HTML 格式的,解壓出來其中 index.html 就是文檔首頁面。頁面左邊的 Quick Search 是離線也可以使用的,有對函數功能有疑惑或者要查詢模組的時候就能在這裡查看。
選擇 PyDev 作為 IDE
Python 整合式開發環境的選擇好像一直以來也是一個很難抉擇的問題。在嘗試過很多個工具後我發現基於 Eclipse 的 PyDev 絕對是功能最為完整的一個 IDE 。除了斷點調試之外,PyDev 的代碼自動補全可能是現在這類別識別碼E 中最強力的。
如果你安裝了 Python(x, y) 的話,PyDev 就已經在你的機器上了。如果沒有的話請按照這篇文章來進行安裝。
設定上有一些需要注意的地方。首先在開啟 PyDev ,開啟菜單中 Window -> Preferences,在彈出對話方塊中左邊找到 PyDev -> Editor -> Code Completion。這裡可以設定代碼自動補全的相關資訊。可以降低 Autocompletion delay 來更早的提示代碼,並且將 Request completion on 系列儘可能勾上,讓 PyDev盡可多的提示代碼。之後再找到 Interpreter Python選項卡,這裡可以設定所謂 Forced Buildins,可以強制引入某些第三方庫從而完成代碼補全。就我的經驗來看大部分第三方庫在這樣設定後都能進行基本的補全。具體的做中,選擇到對應的選項卡,點擊 New,並輸入你需要的模組名字即可。
設定後總體效果絕對是同類IDE中比較好的:
IPython 替代 Python Shell
在學習 Python 的時候應該都接觸過 Python 的 Shell,能夠輸入 Python 語句並且立即返回結果。而 IPython就是一個豪華加強版的 Python Shell。如果你安裝了 Python(x, y) 的話,那 IPython 已經在你的機器上了。如果沒有的話那麼請在這裡下載 Windows Installer 進行安裝。在安裝這個之後還需要安裝 pyreadline 讓 IPython 開啟高亮和自動補全功能。
之後你在命令列下需要 python 的時候改為輸入 ipython就能使用它了。開啟 IPython 看看,首先感覺的不同應該是這個是有顏色的。我們來看看它提供的一些基礎而實用的功能吧。首先是自動補全,一種是簡單的關鍵字補全,另外一種是對象的方法和屬性補全。作為例子,我們先引入 sys模組,之後再輸入 sys.(注意有個點),此時按下 tab 鍵,IPython 會列出所有 sys 模組下的方法和屬性。因為是在互動模式下進行的,此時的 Python 語句實實在在的被執行了,所以對普通 object 的補全也是很完好的。
接著上面的例子,我們輸入 sys?,這樣會顯示出 sys模組的 docstring及相關資訊。很多時候這個也是很方便的功能。
IPython 另外還有很多方便的功能,可以自己參閱文檔來發掘。這裡另外介紹一個很神奇的功能。如果你的程式是由命令列開始執行的,即在命令列下輸入
python foo.py(大部分 Python 程式都是),那麼你還可以利用 IPython 在你的程式任意地方進行斷點調試!在你程式中任意地方,加入如下語句:
from IPython.Shell import IPShellEmbed IPShellEmbed([])()
再和平常一樣運行你的程式,你會發現在程式運行到插入語句的地方時,會轉到 IPython 環境下。你可以試試運行些指令,就會發現此刻 IPython 的環境就是在程式的那個位置。你可以逐個瀏覽目前狀態下的各個變數,調用各種函數,輸出你感興趣的值來協助調試。之後你可以照常退出 IPython,然後程式會繼續運行下去,自然地你在當時 IPython 下執行的語句也會對程式接下來的運行造成影響。
這個方法我是在這裡看到的。想象一下,這樣做就像讓高速運轉的程式暫停下來,你再對運行中的程式進行檢查和修改,之後再讓他繼續運行下去。這裡舉一個例子,比如編寫網頁 bot ,你在每取回一個頁面後你都得看看它的內容,再嘗試如何處理他獲得下一個頁面的地址。運用這個技巧,你可以在取回頁面後讓程式中斷,再那裡實驗各種處理方法,在找到正確的處理方式後寫回到你的代碼中,再進行下一步。這種工作流程只有像 Python 這種動態語言才可以做到。
ipython與Linux的完美結合
當然Ipython最NB的地方在於和Linux系統的無縫串連,簡單介紹一下在Ubuntu下的使用,首先需要安裝Ipython:
root@3414-mainsrv:~# sudo apt-get install ipython
接著就可以在終端下使用了,有個一個稱為是magic的函數:
In [1]: magic
IPython's 'magic' functions
===========================
The magic function system provides a series of functions which allow you to
control the behavior of IPython itself, plus a lot of system-type
features. All these functions are prefixed with a % character, but parameters
are given without parentheses or quotes.
NOTE: If you have 'automagic' enabled (via the command line option or with the
%automagic function), you don't need to type in the % explicitly. By default,
IPython ships with automagic on, so you should only rarely need the % escape.
Example: typing '%cd mydir' (without the quotes) changes you working directory
to 'mydir', if it exists.
You can define your own magic functions to extend the system. See the supplied
ipythonrc and example-magic.py files for details (in your ipython
configuration directory, typically $HOME/.ipython/).
You can also define your own aliased names for magic functions. In your
ipythonrc file, placing a line like:
execute __IPYTHON__.magic_pf = __IPYTHON__.magic_profile
will define %pf as a new name for %profile.
You can also call magics in code using the ipmagic() function, which IPython
automatically adds to the builtin namespace. Type 'ipmagic?' for details.
For a list of the available magic functions, use %lsmagic. For a description
of any of them, type %magic_name?, e.g. '%cd?'.
我們來舉個例子把,例如有一個稱為是bg的魔法函數,它的作用是用來在後台進行計算,我們需要計算一下2的10次方,只需要按下面輸入即可交給bg函數把計算丟到後台去計算而不影響你的繼續操作,你只要記得job的序號是1,需要結果時,只要把jobs[1]中的result輸出就可以了
In [10]: bg pow(2,10)
Starting job # 1 in a separate thread.
In [11]: print jobs[1].result
1024
此外,使用rehash函數,你完成可以把ipython當做是shell使用,你可以使用任何命令,例如:
In [15]: ps aux|grep DarwinStreamingSrvr
root 17496 0.0 0.0 2040 508 pts/0 S+ 10:12 0:00 sh -c ps aux|grep DarwinStreamingSrvr
root 17498 0.0 0.0 7368 852 pts/0 S+ 10:12 0:00 grep DarwinStreamingSrvr
pip 管理第三方庫
Python 的一大優勢就是有極為大量的第三方庫,包括各個方面的引用。然而安裝第三方庫對沒有掌握方法的同學來說會變得很讓人煩惱。事實上 Python 第三方庫的安裝和管理有著一個一個唯一正確的做法,這個做法要求你什麼其他的都不用幹,只要輸入你要安裝庫的名字就可以了。
setuptools 也包在 Python(x, y) 當中。如果沒有的話,要首先先安裝 setuptools ,這個其實就是一個安裝第三方庫的軟體。選擇對應版本的 Windows Installer 進行下載和安裝後,開啟一個命令列視窗,輸入:
easy_install pip
如果提示找不到程式,那麼說明你當前沒有設定好環境變數。安裝官方提供的 Python 安裝包的話肯定會有這個問題,而且很可能暫時不會修正,這就是牛逼程式員的倔強。具體做法是 右鍵我的電腦 - 屬性 - 進階系統設定 - 環境變數 - 將 C:\python2*\Scripts加入到 PATH 那一組當中。這樣做的效果就是在任何地方的命令列下輸入命令,那麼系統會額外尋找我們設定的那個目錄中的內容。之後再執行上面的命令,裝好了以後我們就要棄用 setuptools,轉投 pip。要安裝任何一個庫,你只要找到他的名字(不需要版本號碼),用 pip 安裝即可。譬如安裝 django,那麼輸入如下命令即可:
pip install django
其實之前 easy_install跟 pip效用是類似的,都是在官方的第三方庫索引 PyPI 查詢資訊並進行下載和安裝。pip 的優勢在於支援更進階的功能,譬如虛擬環境,安裝失敗不會殘留破損的庫,更重要的是 pip 還可以進行卸載。輸入下面命令就能卸載一個之前由 pip 進行安裝的庫。繼續上面的例子,現在要卸載 django:
pip uninstall django
這是 setuptools 所缺失的功能。需要額外說明的是大部分純 Python 的庫都能用這個方法在 Windows 下裝上,但是需要編譯 C 語言模組的一般都不太可能成功。遇到這種情況,在相應的庫德網站上找找有沒有對應的 Windows 安裝包。
Winpdb
如果你使用的 PyDev 的話那麼用其內建的斷點調試應該就可以了。Winpdb則是為用其他簡單編輯器進行 Python 開發的使用者提供一個熟悉的調試環境。Winpdb不出意料的也在 Python(x, y)當中。所以如果裝上 Python(x, y) 你可以不斷髮掘裡面附帶的優秀工具。使用方法很簡單,假設程式名為 foo.py,那麼在命令列中輸入:
winpdb foo.py
之後會快顯視窗,也就是一個大家都熟悉的 debug 圖形介面。需要注意的是這裡需要點擊想要設定斷點的行,點擊 F9 設定斷點,然後該行底色會變為紅色,如所示。
編碼問題
作為中文使用者,初學 Python 最容易碰到的問題估計就是編碼問題了。明明英文的都可以用到中文的時候就要出問題,而且出錯資訊難以理解,想要解決問題又不知道從何開始。幸運的是編碼問題通過預防性的措施是很好避免的。下面從幾個方面來講講 Python 中處理中文及 Unicode 容易碰到的問題。
Unicode 編碼基礎
這裡非常簡單的講一下編碼知識,此部分表述可能不太準確,如果你對 Unicode 更為瞭解的話請聯絡我幫忙糾正。
你可以想象 Unicode 是一個很大的表,裡面有著世界上所有的文字的個體,如英文中的字母,中文的漢字。事實上 Unicode 標準中每一個字都有一個唯一對應的編號,好比說 '中'字 對應十六進位 0x4E2D,而字母 'a' 對應的是十六進位 0x0061。這個編號是由 Unicode Consortium 這個組織來確定的。 如果說用這個編碼來對應字元來用於表示字元,理論上是可以的,這樣的話就是每一個數字編號能對應一個字元。
而實際情況中,不是每篇文章都用得到世界上所有的字元。譬如一篇英文文章就只有英文字母加上一些符號,用 Unicode 來進行儲存的話每個字元要浪費太多的空間。所以就有各種類型的編碼產生。編碼我們這裡可以理解就是將一部分的 Unicode (比如說所有的中文,或者所有的日文)字元,以某種方式確定另外一個符號來代表他。中文常用編碼有 UTF8 和 GBK,仍然以 '中'字 為例, UTF8 編碼將對應 '中'字 的 Unicode 編號 0x4E2D拆成三個的編號的組合,[0xE4, 0xB8, 0xAD],只有這幾個連在一起的時候才會被作為一個 '中'字 顯示出來;作為對比,GBK 編碼將 '中'字 對應的 Unicode 編號 0x4E2D編碼成為兩個編號的組合
[0xD6, 0xD0],在 GBK 編碼環境下只有這兩個編號一起時,才會顯示為 '中'字。
上面的例子中,如果把 UTF8 編碼後的 [0xE4, 0xB8, 0xAD]放到 GBK 環境下來顯示會怎樣?這幾個編號跟 '中'字 在 GBK 下的編碼 [0xD6, 0xD0]
,不同,則顯然不會顯示為 '中'字。這三個字元會跟排在其前後的字元一起,按照 GBK 的編碼規則找有沒有對應的字元。結果有可能顯示出一個毫不相關的字元,有時候為符號或者乾脆不顯示,這種情況就算產生了亂碼。
Python 2.x 中的 String 與 Unicode
在 Python 2.x 中是有兩種字串符相互關聯類型的,分別為 String 和 Unicode,兩者提供的介面非常類似,有時候又能自動轉換,蠻容易誤導人的。在 Python 3 中 這兩個類型分別用 Bytes 和 String 替代了。這個名字更能說明兩者的本質:Python 2.x 中的 String 中儲存的是沒有編碼資訊的位元組序列,也就是說 String 中儲存的是已經編碼過後的序列,但他並不知道自身是用的哪種編碼。相反的 Unicode 中儲存的是記載了編碼的字串資訊,其中儲存的就是相應字元的 Unicode 編號。在這裡用程式來說明,我們建立一個簡單的指令碼名字為 encoding.py,代碼如下:
#!/usr/bin/python
# -*- coding: utf-8 -*-
strs = "這是中文"
unis = "這也是中文".decode("utf8")
print strs[0:2]
print unis[0:2].encode('gbk')
print len(strs)
print len(unis)
前面兩行後面會解釋到,就是限定運行環境以及該指令檔的編碼格式。此指令碼在這裡可以下載,如果你要自己寫的話請務必確保指令碼的編碼是 utf8 而不是別的。在 Windows 下的運行結果在這裡,我覺得正好能說明問題:
C:\SHARED\Dev\scripts>encoding.py
這裡需要說明,我們的程式是 UTF8 編碼,主要意義是該程式中的所有直接寫出來的字串符(用"", ''括起來的字串符)是運用 UTF8 格式編碼的;然而Windows 下的命令列是 GBK 環境。這裡 strs是一個 String。事實上在 Python 2.x 中直接寫在程式中的字串符,其類型都是 String(這裡不考慮 string literal)。我們先直接輸出 strs[0:2],得到的是一個亂碼字元(這個字元只是碰巧湊成是一個字)。如上面說的,String中儲存的是沒有編碼資訊的字串序列,這裡就是將strs中前兩個編號取出並嘗試顯示。由於命令列環境為 GBK 編碼,這裡對應的字碰巧湊成了一個字,但是跟原本的字沒有任何關係。
unis是由一個 String調用 decode()方法得到,這正是在 Python 2.x 中取得 Unicode的最基本的方式。由於 String並不知道它本身是由什麼編碼格式來進行的編碼,這裡是我們的責任來確定他原來是用哪種編碼方式進行編碼。我們知道代碼中的編碼格式是 UTF8,所以我們可以用調用 String的 decode()方法來進行反編碼,也就是解碼, 把字串符從某種編碼後的格式轉換為其唯一對應的 Unicode 編號。unis為解碼獲得的結果,其在 Python 2.x 中對應類型就是 Unicode,其中儲存的就是 每個字元對應的 Unicode 編號。
我們嘗試輸出 unis的前兩個字元,在這裡我們調用了 Unicode的 encode()方法。這就是編碼的過程。我們知道 Windows 命令列下的編碼是 GBK,只有採用 GBK 編碼的字元才能正確顯示。所以在這裡我們通過調用 Unicode的 encode()方法,將 unis中儲存的 Unicode 編號 按照 GBK 的規則來進行編碼,並輸出到螢幕上。這裡我們看到這裡正確的顯示了 unis中的前兩個字元。要注意的是在命令列中直接 print Unicode的話 Python 會自動根據當前環境進行編碼後再顯示,但這樣掩蓋了兩者的區別。建議總是手動調用 encode和 decode方法,這樣自己也會清楚一些。
後面兩者長度的差別也是佐證我們之前的例子。
strs中儲存的是 UTF8 編碼後的編號序列,上面看到一個中文字元在 UTF8 編碼後變成三個連續的,所以 strs長度為 3x4 = 12。你可以想象 strs中存放的並不是中文,而是一系列沒有意義的位元序列;而 unis中儲存的是對應的中文的 Unicode 編碼。我們知道每一個字元對應一個編號,所以五個字對應五個編號,長度為 5。避免,和解決編碼產生的問題
瞭解了 Python Unicode 編碼解碼的這些概念後,我們來看看如何盡量的避免遇到讓人煩心的編碼問題。
首先如果你的代碼中有中文,那麼一定要務必聲明代碼的編碼格式。根據 PEP-0263 中的介紹,在程式的最開始加上以下兩行注釋就能確定編碼:
#!/usr/bin/python
# -*- coding: utf-8 -*-
其中 utf-8就是指定的編碼格式。事實上你應該總是使用 UTF8 作為你 Python 程式的編碼格式,因為未來的 Python 3 所有檔案都將預設以 UTF8 編碼。另外除了聲明,你必須確定你用來編輯 Python 程式的編輯器是不是真的以 UTF8 編碼來隱藏檔。
之後就是養成關於編碼解碼的好習慣。當你的程式有 String作為輸入時,應該儘早的將其轉換為 Unicode,再在程式中進行處理。再輸出的時候,也要儘可能玩,直到最後輸出的時刻才將 Unicode編碼為所需編碼格式的 String進行輸出。同樣的你必須保持你程式內部所有參與運算的字串都是 Unicode格式。很多著名的 Python 庫例如 django 就是採用的這種方式,效果也蠻好。千萬不要依賴 Python 自己進行兩者之間的轉換,也不要將 String和 Unicode放在一起運算,這些行為一方面十分容易引起錯誤,另一方面在 Python 3 中已經無法再現。雖說確定 String的編碼格式是程式員的責任,但有時候你真的不知道有些字串符到底是什麼編碼的。這裡有一個神奇 chardet 能夠協助你。以下是摘自其頁面上的例子,很好了說明了它的作用:讀入任意一串字元,猜測其編碼格式,並且給出猜測的確信度。
>>> import urllib
>>> urlread = lambda url: urllib.urlopen(url).read()
>>> import chardet
>>> chardet.detect(urlread("http://google.cn/")) {'encoding': 'GB2312', 'confidence': 0.99}
>>> chardet.detect(urlread("http://yahoo.co.jp/")) {'encoding': 'EUC-JP', 'confidence': 0.99}
>>> chardet.detect(urlread("http://amazon.co.jp/")) {'encoding': 'SHIFT_JIS', 'confidence': 1}
>>> chardet.detect(urlread("http://pravda.ru/")) {'encoding': 'windows-1251', 'confidence': 0.9355}
如果 confidence 非常低的話或者 chardet 直接報錯,多半是字串經過多次錯誤編碼解碼,要從別的地方找辦法解決問題。
如果上面的介紹還不能讓你理解 Unicode 的概念,這裡還有幾篇關於這個問題的文章:
介紹 Unicode 的兩篇文章 [1], [2]。關於 Unicode 有更為詳細的解釋。
Unicode In Python, Completely Demystified 特別針對 Python 下的 Unicode 處理進行詳細的講解。
其他除了上面幾個重要的問題之外,剩下的資源。
Vim Python開發 相關資源
事實上我現在自己是在用 Vim 寫 Python,感覺也蠻不錯。以下是相關資源。
UltimateVimPythonSetup 比較新的一個專門針對 Python 的 Vim 設定檔。
Vim as Python IDE 只要搜 Python 和 Vim 就一定會找到這一篇文章。
vimcolorschemetest 所有的Vim 色彩配置都在集結在這裡。
Python 相關 Vim 外掛程式
pythoncomplete.vim 按上面的介紹配置一下,在自動輸入的時候按Ctrl-X, Ctrl-O就有很強力的自動補全了。
python.vim 加強文法的高亮。
pyflakes.vim 很棒的語法檢查,分析你的文法看避免低級錯誤。注意這個在Vim7.2下才有用, 如果是7.1則一點效果都沒有...
其他相關資源
用Python做科學計算
這個把Python(x,y)裡面所有的模組基本上都講了一遍,我覺得外國人肯定都希望這個有個英文版的。
PyMOTW
這個名字看起來像個Python庫(其實它還真的是一個...),但他總體來說其實是一份文檔, "Python每周一個模組"。作者持續幾年每周介紹一個Python標準庫中的庫。你可以把他看做是一個Python標準庫文檔的一個很棒的補充,當你看標準庫中的介紹看的雲裡霧裡的時候,不妨來這邊找找相應的介紹。因為這裡的例子給的很全,而且基本上你用的到的偏門的庫這裡都有介紹哦。另外一個好訊息是PyMOTW有一份很棒中文翻譯版。
reddit.com/r/python 和 python.org planet
Python 相關的文章和資源。就我個人經曆來說,每次都能在這裡看到很多有用的東西。