引言
在這里我假設(shè)你已經(jīng)看完了一篇Python教程,基本熟悉了Python的結(jié)構(gòu)和語法耿戚,在命令行下的Python互動環(huán)境中嘗試過大部分Python的語句窒典,覺得Python是個不錯的語言準備繼續(xù)下去蟆炊。那么本篇文章會就Python實際運用中相關(guān)工具的選擇,包括IDE瀑志,調(diào)試套件涩搓,第三方庫管理工具這些進行介紹污秆。另外還會對某些中文環(huán)境下容易遇到的問題,例如unicode編碼解碼的問題進行說明昧甘。本文主要是針對 Windows 環(huán)境下的 Python 開發(fā)進行說明良拼。文章的目的是為了分享些我覺得很有用的經(jīng)驗和例子,若發(fā)現(xiàn)文中有疏漏之處請務(wù)必聯(lián)系我疾层。謝謝将饺。
Python 語言介紹
Python 是一個近些年在開始流行起來的計算機編程語言贡避。根據(jù)Python官網(wǎng)上的簡介痛黎,Python主要特性包括跨平臺,免費刮吧,簡單且容易維護湖饱。就我個人理解來說,Python是一門適合大部分人的語言杀捻,因為各種類型的第三方庫都有井厌,所以像簡單桌面程序,動態(tài)網(wǎng)站開發(fā)致讥,圖像處理仅仆,表格處理,甚至自動發(fā)帖機這些小應(yīng)用在簡單的學(xué)習(xí)后垢袱,不需要很深厚的編程經(jīng)驗的人應(yīng)該都能自己做出來墓拜。
一些流行的Python教程有:
Dive into Python面向有一定編程基礎(chǔ)的同學(xué)。另外還有Dive into Python 3请契,針對Python3的教程咳榜。
Learn Python The Hard Way,書中主要是通過各種練習(xí)來進行學(xué)習(xí)爽锥,面向完全沒有編程經(jīng)驗的同學(xué)涌韩。
Invent Your Own Computer Game With Python,讓你一上手就做個游戲出來的教程氯夷,厲害吧臣樱。
The Python Tutorial,官方文檔中的教程腮考,正統(tǒng)而完整擎淤。
如果你還沒有開始接觸 Python ,或者覺得還不夠熟悉秸仙,那么不妨找一份你覺得看得下去的教程開始學(xué)習(xí)吧嘴拢。就我個人經(jīng)驗來說,Python 是我到目前為止覺得學(xué)的最劃得來的一門語言寂纪,也是日常用的最多的一門席吴,而事實上你并不需要了解完全了解 Python 就能在開始使用它赌结。
Python 版本選擇,其他發(fā)行版
Python 2 與 3
Python 2 和 3 系列的選擇可能是比較讓人煩躁的事情孝冒。其實區(qū)別很簡單:Python 3.x 各個方面都更好柬姚,但語法與 Python 2.x 很大部分不兼容。Python 2.x 已經(jīng)停止繼續(xù)開發(fā)庄涡。但是目前很多第三方庫仍然不支持 Python 3 , 文章后面介紹的很多工具量承,特別是科學(xué)計算的庫仍然只支持 Python 2.x。
原來這里寫的推薦版本是 2.6穴店,現(xiàn)在的情況是 2.7 版本是 2.x 系列最后一個大版本號撕捍,以后只會有 2.7.x 的維護版本并不再會添加新功能。Python 3 現(xiàn)在已經(jīng)足夠成熟泣洞,很多常見的庫都已經(jīng)移植到 Python 3 上了忧风。所以現(xiàn)在如果你是自己學(xué) Python 那么上來直接 Python 3 沒啥問題,但如果你是在工作的地方或者對科學(xué)計算有要求那么還是需要 Python 2.7 比較好球凰。
這里我發(fā)現(xiàn)有一個比較靠譜的選擇辦法狮腿,就是看 Python(x,y) 帶的 Python 版本。它現(xiàn)在還是在 2.7呕诉,這個版本基本上所有的第三方庫都在支持缘厢。當(dāng)哪一天 Python(x,y) 上到 Python 3 了那估計就是可以安心用 Python 3 的時候了。但按現(xiàn)在這個情況估計還得好幾年吧甩挫。
發(fā)行版
目前在 Windows 下除了官方提供的安裝版外贴硫,還有:
ActivePython,這個與官方版本的區(qū)別在于提供了額外的庫和文檔捶闸,并且自動設(shè)置了PATH環(huán)境變量(后文會詳細提到)
Python(x,y)夜畴,這個是我一直用并且推薦給別人用的版本。從名字就能看出來這個發(fā)行版附帶了科學(xué)計算方面的很多常用庫删壮,另外還有大量常用庫比如用于桌面軟件界面制作的PyQt, 還有文檔處理贪绘,exe文件生成等常用庫。另外的還有大量的工具如IDE央碟,制圖制表工具税灌,加強的互動shell之類。很多下文提到的軟件在此發(fā)行版中都有附帶亿虽。其他方面菱涤,Python(x, y)還附帶了手工整理出的所有庫的離線文檔,每個小版本升級都提供單獨的補丁洛勉≌掣眩總的來說是很用心維護的一個發(fā)行版,十分建議安裝這個版本收毫。
Conda, 一個類似 Python(x, y) 的輕量級發(fā)行版攻走。他支持的庫稍微少一點但是常用的也基本包括了殷勘,它提供了一個額外的包裹管理命令還支持 Python 3.x,同時提供簡潔版的Miniconda供自己手動選擇庫進行下載昔搂。
開發(fā)相關(guān)工具
首先玲销,你需要一份文檔
對于 Python 這樣的語言,你覺得你學(xué)到什么時候算是完全掌握呢摘符?你也許會想也許哪一天你記得大部分函數(shù)的名字很怎么用贤斜,不用打幾行就 Google 搜一下的時候,就算學(xué)會了逛裤。這樣的理解對了一半瘩绒,等你熟悉 Python 以后你的卻不應(yīng)該常搜索;但前一半?yún)s不一定别凹,我個人認為你并不需要記住龐大的標準庫中的內(nèi)容草讶,很多時候你只要清楚要在哪里能找到相應(yīng)的文檔就行了洽糟。
Python 在這方面可以說是做的非常非常非常好炉菲。在真正著手開發(fā)之前,你應(yīng)該在下載一份離線的文檔坤溃。在這個頁面(如果打不開的話試試這里拍霜,你懂的)下載一份 HTML 格式的,比如是 2.7.3 版那么對應(yīng)的文檔名字應(yīng)該是python-2.7.3-docs-html.zip薪介。下好后把它在一個你喜歡的地方解壓出來祠饺,打開其中的index.html,這就是這個文檔的主頁汁政。你可以看到他分為很多部分道偷,包括語言的參考,標準庫和其他很多方便的文檔记劈。
如果你一下不知道從哪里看起勺鸦,這份文檔還有一個非常棒的功能∧磕荆看到左邊的Quick Search欄换途,我在上圖中也有標注起來。當(dāng)你需要對某個函數(shù)或者標準庫進行進一步了解的時候刽射,你可以在這邊來進行搜索军拟。這里的搜索是火星科技驅(qū)動的離線狀態(tài)下也能夠使用的!比如輸入urllib.urlencode誓禁,你可以很方便的找到它對應(yīng)的頁面懈息。基本有了這份文檔摹恰,你可以避免掉很多瘋狂搜索的情況辫继。同樣的阁最,當(dāng)你使用某個第三方庫的時候,你最好也在他的站點上找找有沒有一份離線文檔骇两,因為 Python 項目很多都有著很贊的文檔速种。
開發(fā)環(huán)境的選擇
如果你選擇用 IDE 的話,現(xiàn)在的選擇就非常多了低千,包括PyCharm,Python Tools for Visual Studio配阵。你也可以硬派一點用一個文本編輯器直接寫。但我強烈建議不要使用 Python 發(fā)行版自帶的那個 IDLE示血。開發(fā)者沒有真的認為誰會仔細用那它棋傍,一直以來沒有什么新功能,運行效率不行难审,而且會出詭異的問題(比如會報什么 socket 錯誤)瘫拣。希望你花些時間找個順手的工具,只要不是 IDLE 就可以告喊。
選擇 PyDev 作為 IDE
Python 集成開發(fā)環(huán)境的選擇好像一直以來也是一個很難抉擇的問題麸拄。在嘗試過很多個工具后我發(fā)現(xiàn)基于 Eclipse 的PyDev絕對是功能最為完整的一個 IDE 。除了斷點調(diào)試之外黔姜,PyDev 的代碼自動補全可能是現(xiàn)在這類 IDE 中最強力的拢切。
如果你安裝了Python(x, y)的話,PyDev 就已經(jīng)在你的機器上了秆吵。如果沒有的話請按照這篇文章來進行安裝淮椰。
設(shè)置上有一些需要注意的地方。首先在打開 PyDev 纳寂,打開菜單中Window -> Preferences主穗,在彈出對話框中左邊找到PyDev -> Editor -> Code Completion。這里可以設(shè)置代碼自動補全的相關(guān)信息毙芜『雒剑可以降低 Autocompletion delay 來更早的提示代碼,并且將 Request completion on 系列盡可能勾上爷肝,讓 PyDev盡可多的提示代碼猾浦。
之后再找到Interpreter Python選項卡,這里可以設(shè)置所謂 Forced Buildins灯抛,可以強制引入某些第三方庫從而完成代碼補全金赦。就我的經(jīng)驗來看大部分第三方庫在這樣設(shè)置后都能進行基本的補全。具體的做如圖中对嚼,選擇到對應(yīng)的選項卡夹抗,點擊 New,并輸入你需要的模塊名字即可纵竖。
設(shè)置后總體效果絕對是同類IDE中比較好的:
IPython 替代 Python Shell
在學(xué)習(xí) Python 的時候應(yīng)該都接觸過 Python 的 Shell漠烧,能夠輸入 Python 語句并且立即返回結(jié)果杏愤。而IPython就是一個豪華加強版的 Python Shell。如果你安裝了 Python(x, y) 的話已脓,那 IPython 已經(jīng)在你的機器上了珊楼。如果沒有的話那么請在這里下載 Windows Installer進行安裝。在安裝這個之后還需要安裝pyreadline讓 IPython 開啟高亮和自動補全功能度液。
之后你在命令行下需要 python 的時候改為輸入ipython就能使用它了厕宗。開啟 IPython 看看,首先感覺的不同應(yīng)該是這個是有顏色的堕担。我們來看看它提供的一些基礎(chǔ)而實用的功能吧已慢。首先是自動補全,一種是簡單的關(guān)鍵字補全霹购,另外一種是對象的方法和屬性補全佑惠。作為例子,我們先引入sys模塊齐疙,之后再輸入sys.(注意有個點)膜楷,此時按下 tab 鍵,IPython 會列出所有 sys 模塊下的方法和屬性剂碴。因為是在互動模式下進行的把将,此時的 Python 語句實實在在的被執(zhí)行了轻专,所以對普通 object 的補全也是很完好的忆矛。
接著上面的例子,我們輸入sys?请垛,這樣會顯示出sys模塊的 docstring及相關(guān)信息催训。很多時候這個也是很方便的功能。
IPython 實用技巧
這里再介紹下 IPython 使用中的一些實用功能宗收。在學(xué)習(xí) Python 時你可能看到在循環(huán)或者函數(shù)返回時可以賦值給_來表示忽略某個返回值漫拭。其實這只是一個常用的習(xí)慣。事實上_是一個合法的變量名混稽,而且在 Python shell 下_總是被賦予之前最后一個輸出的值。這里看個例子應(yīng)該就能清楚:
>>> import string
>>> string.letters
'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ
>>> print _
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ
舉個實際的例子,比如你在調(diào)試時讀文件的時候直接進行f.read()强重,你看了看發(fā)現(xiàn)輸出結(jié)果很有意思庆揩,想要對它進行進一步處理,但發(fā)現(xiàn)讀的時候忘記賦值了洽洁。以往你只能嘆嘆氣重新開文件再讀一次痘系,現(xiàn)在你只要執(zhí)行result = _,把_附到另外一個變量就可以了饿自。
IPython 還有強大之處很大部分還體現(xiàn)在它的magic function中汰翠。它是指的在 IPython 環(huán)境下執(zhí)行以%開頭的一些命令來對 IPython 進行一些設(shè)定或者執(zhí)行某些功能龄坪。在 IPython 中輸入%lsmagic就能列出所有的magic functions。在這里簡單介紹下幾個比較有意思的复唤,你也可以自己通過查看文檔來找找有哪些你特別用的到得健田。
之前看到能用?來查詢函數(shù)的文檔,對于 magic function 也是如此佛纫。比如%run?抄课。
!cd ..在命令前面加上!則它會被作為命令行命令執(zhí)行,這樣你就不用退出 IPython 來進行命令行操作雳旅。
%run foo.py在當(dāng)前環(huán)境下直接執(zhí)行foo.py跟磨,效果跟命令行下調(diào)用ipython foo.py相同。
%time foo.bar()跟timeit decorator作用相同攒盈,進行簡單的 profile抵拘。
%hist能顯示之前輸入過的命令的歷史,同時你可以用In[]來訪問之前的命令型豁。比如%exec In[10]就能執(zhí)行列表中第十行僵蛛。
%rep類似上面的_變量,但是是以字串的形式返回
最后迎变,如果%automagic是打開的狀態(tài)的話充尉,所有 magic function 不需要在前面加%就能正確調(diào)用。
在當(dāng)前 IPython 版本中還有一個由于安全原因沒有默認引入的%autoreload衣形,它的作用是在可以自動重新載入你調(diào)用的函數(shù)驼侠,以及其相關(guān)模塊。接觸過django的同學(xué)對這個應(yīng)該比較熟悉谆吴,在 IPython 中的效果就是倒源,當(dāng)你在調(diào)試一個一直在反復(fù)改動的函數(shù)時,你可以開啟這個功能保證每次調(diào)用都會重新讀取最新的版本句狼,讓你在源碼中的改動馬上生效笋熬。在 IPython 中執(zhí)行
import ipy_autoreload
%%autoreload 2
這樣 IPython 會對所有的模塊都進行 autoreload。你可以通過執(zhí)行%autoreload?來查詢它的文檔來進行進一步設(shè)定腻菇。如果你希望 IPython 每次啟動自動載入次功能胳螟,那么可以通過配置 ipythonrc (在 Windows 下可以在C:\Users\\_ipython\ipythonrc.ini找到) 來進行相關(guān)設(shè)置。
最后還有一個很神奇的功能筹吐。如果你的程序是由命令行開始執(zhí)行的糖耸,即在命令行下輸入python foo.py(大部分 Python 程序都是),那么你還可以利用 IPython 在你的程序任意地方進行斷點調(diào)試骏令!在你程序中任意地方蔬捷,加入如下語句:
from IPython.Shell import IPShellEmbed
IPShellEmbed([])()
注意:最近 IPython 發(fā)布了0.11 版本,各方面變化都非常大,API 也經(jīng)過了重新設(shè)計周拐。如果你使用的是 0.11 那么上面兩行對應(yīng)的是這樣的:
from IPython import embed
embed()
再和平常一樣運行你的程序铡俐,你會發(fā)現(xiàn)在程序運行到插入語句的地方時,會轉(zhuǎn)到 IPython 環(huán)境下妥粟。你可以試試運行些指令审丘,就會發(fā)現(xiàn)此刻 IPython 的環(huán)境就是在程序的那個位置。你可以逐個瀏覽當(dāng)前狀態(tài)下的各個變量勾给,調(diào)用各種函數(shù)滩报,輸出你感興趣的值來幫助調(diào)試。之后你可以照常退出 IPython播急,然后程序會繼續(xù)運行下去脓钾,自然地你在當(dāng)時 IPython 下執(zhí)行的語句也會對程序接下來的運行造成影響。
這個方法我實在這里看到的桩警。想象一下可训,這樣做就像讓高速運轉(zhuǎn)的程序暫停下來,你再對運行中的程序進行檢查和修改捶枢,之后再讓他繼續(xù)運行下去握截。這里舉一個例子,比如編寫網(wǎng)頁 bot 烂叔,你在每取回一個頁面后你都得看看它的內(nèi)容谨胞,再嘗試如何處理他獲得下一個頁面的地址。運用這個技巧蒜鸡,你可以在取回頁面后讓程序中斷胯努,再那里實驗各種處理方法,在找到正確的處理方式后寫回到你的代碼中术瓮,再進行下一步康聂。這種工作流程只有像 Python 這種動態(tài)語言才可以做到。
pip 管理第三方庫
Python 的一大優(yōu)勢就是有極為大量的第三方庫胞四,包括各個方面的引用。然而安裝第三方庫對沒有掌握方法的同學(xué)來說會變得很讓人煩惱伶椿。事實上 Python 第三方庫的安裝和管理有著一個一個唯一正確的做法辜伟,這個做法要求你什么其他的都不用干,只要輸入你要安裝庫的名字就可以了脊另。
setuptools 也包在 Python(x, y) 當(dāng)中导狡。如果沒有的話,要首先先安裝setuptools偎痛,這個其實就是一個安裝第三方庫的軟件旱捧。選擇對應(yīng)版本的 Windows Installer 進行下載和安裝后,打開一個命令行窗口,輸入:
easy_install pip
如果提示找不到程序枚赡,那么說明你當(dāng)前沒有設(shè)定好環(huán)境變量氓癌。安裝官方提供的 Python 安裝包的話肯定會有這個問題,而且很可能暫時不會修正贫橙,這就是牛逼程序員的倔強贪婉。具體做法是 右鍵我的電腦 - 屬性 - 高級系統(tǒng)設(shè)置 - 環(huán)境變量 - 將C:\python2*\Scripts加入到 PATH 那一組當(dāng)中。這樣做的效果就是在任何地方的命令行下輸入命令卢肃,那么系統(tǒng)會額外查找我們設(shè)定的那個目錄中的內(nèi)容疲迂。之后再執(zhí)行上面的命令,裝好了以后我們就要棄用 setuptools莫湘,轉(zhuǎn)投pip尤蒿。要安裝任何一個庫,你只要找到他的名字(不需要版本號)幅垮,用 pip 安裝即可优质。譬如安裝django,那么輸入如下命令即可:
pip install django
其實之前easy_install跟pip效用是類似的军洼,都是在官方的第三方庫索引PyPI查詢信息并進行下載和安裝巩螃。pip 的優(yōu)勢在于支持更高級的功能,譬如虛擬環(huán)境匕争,安裝失敗不會殘留破損的庫避乏,更重要的是 pip 還可以進行卸載。輸入下面命令就能卸載一個之前由 pip 進行安裝的庫甘桑。繼續(xù)上面的例子拍皮,現(xiàn)在要卸載 django:
pip uninstall django
這是 setuptools 所缺失的功能。需要額外說明的是大部分純 Python 的庫都能用這個方法在 Windows 下裝上跑杭,但是需要編譯 C 語言模塊的一般都不太可能成功铆帽。遇到這種情況,在相應(yīng)的庫德站點上找找有沒有對應(yīng)的 Windows 安裝包德谅。
用 virtualenv 構(gòu)建虛擬 Python 環(huán)境
如果你使用過 Python 做過 Web 開發(fā)爹橱,或者你有需求在本機上安裝多個版本的 Python 來測試你的代碼能否跑再 2.5, 2.6, 2.7 各個版本上,或者你的不同項目依賴于一個第三方庫的不同版本窄做;再或者愧驱,有時候你就是想要一個沒有之前安裝過的亂七八糟的庫,一個干凈的 Python 環(huán)境椭盏。這種時候virtualenv就能幫上你的忙组砚。它能利用安裝好的 Python ,在同一臺機器上建立一個或多個互不相干的虛擬 Python 環(huán)境掏颊,且能隨時切換糟红。如果你看到這里還不覺得這個有什么用處,那不妨看下去留下點印象,等哪天你有這類需求的時候能找到這個簡單實用的工具盆偿。
和其他第三方庫一樣柒爸,我們可以通過 pip 輕松安裝:
pip install virtualenv
安裝完成后你可以開啟一個命令行窗口,輸入virtualenv看看能不能找到這個腳本陈肛。如果有問題的話揍鸟,請按照上面介紹過的步驟檢查下是否設(shè)置好了 PATH。之后我們可以在一個方便的地方建立一個虛擬環(huán)境句旱。建立C:\envs\文件夾阳藻,命令行下 cd 到該文件夾中,輸入:
virtualenv --no-site-packages --python=C:\Python26\python.exe envtest
之后應(yīng)該會看到一個叫envtest的文件夾谈撒。這就是一個新建立的虛擬環(huán)境(virtual enviroment)腥泥。我們不妨先激活它來看看應(yīng)該怎么用。命令行下執(zhí)行envtest\Scripts\activate.bat啃匿,這時是你會發(fā)現(xiàn)命令行變成這個樣子:
(envtest) c:\>
提示符前面的(envtest)就是該環(huán)境已被激活的標志蛔外。這樣你就可以在這個虛擬環(huán)境下進行工作了。執(zhí)行pip freeze溯乒,你會發(fā)現(xiàn)... 你會發(fā)現(xiàn)什么都沒有啊夹厌。執(zhí)行pip help,你可以看到pip freeze是輸出當(dāng)前 Python 環(huán)境下已經(jīng)安裝的所有第三方庫裆悄。因為我們創(chuàng)建此環(huán)境時開啟了選項--no-site-packages矛纹,意思就是在創(chuàng)建此虛擬環(huán)境中不從系統(tǒng) Python 中把已經(jīng)安裝了的庫也安裝到這里來,所以這里是一個干凈的新 Python 環(huán)境光稼。你可以在這里調(diào)用pip或者easy_install來安裝各種你需要的庫到這個環(huán)境中來或南,而不會影響到你系統(tǒng)中 Python 的情況,所以說它是一個虛擬的Python 環(huán)境艾君。
我們再回頭看下envtest目錄的結(jié)構(gòu)采够,其下面的Scripts目錄中有python.exepip.exe這些程序,在虛擬環(huán)境已激活的情況下冰垄,你調(diào)用python或者pip都是調(diào)用的此目錄中的程序蹬癌。此時系統(tǒng)中的python.exe被 virtualenv 通過設(shè)置環(huán)境變量隱藏了起來。而Lib目錄下就是存放各種新安裝的庫播演。
到這里你應(yīng)該已經(jīng)對 virtualenv 基本操作已經(jīng)了解了冀瓦,下面講些使用上的注意事項:
調(diào)用activate.bat開啟虛擬環(huán)境,你也可以用同目錄下的deactivate.bat來退出該虛擬環(huán)境写烤。
建立虛擬環(huán)境時的參數(shù)--python=C:\Python26\python.exe是用來指定你想使用 Python 程序位置,所以你可以建立多個虛擬環(huán)境來指向多個 Python 版本拾徙。另外你要注意的是如果你在系統(tǒng)上安裝了多個版本的 Python洲炊, 你最先安裝的一個版本會被當(dāng)做主要版本,你在命令行下打python時,調(diào)用的就是最先安裝的一個版本暂衡。其實這個是按照 PATH 中設(shè)定的路徑位置來確定的询微,你最好把你需要主要使用的版本相關(guān)路徑放在 PATH 環(huán)境變量中最前面。比如我的機器上狂巢,就是把C:\Python26和C:\Python26\Scripts作為 PATH 最前面兩個撑毛。這樣應(yīng)該就能讓保證你主要版本的正常使用。
當(dāng)你在一個虛擬環(huán)境下工作時唧领,假如你想在當(dāng)前環(huán)境下來執(zhí)行一個 Python 程序藻雌,這時你在命令行下必須執(zhí)行python foo.py,這樣 foo.py 才會在你當(dāng)前已經(jīng)激活的 virtualenv 下執(zhí)行斩个。作為比較如果你直接執(zhí)行foo.py那么它仍然時在系統(tǒng)環(huán)境下執(zhí)行的胯杭。
另外,Linux 下可以使用virtualenvwrapper來進行方便的管理和切換各個環(huán)境受啥,可惜的是這東西在 Windows 下用不了做个。但幸好有一個簡單的腳本envdotpy來幫助你使用。把env.py放到 PATH 上的目錄內(nèi)滚局,譬如C:\Python26\Scripts下居暖。之后先打開里面的DEFAULT_DIR_PATH變量,把它改成你集中存放 virtualenv 的地方藤肢,在我們上面的例子中就可以把這行改為:
DEFAULT_DIR_PATH = "C:\\envs\\"
之后你就不需要專門 cd 到這個目錄太闺,而可以在任意路徑上通過env.py來進行激活,切換谤草,退出 virtualenv 了跟束。例如執(zhí)行:env.py envtest就能激活envtest。執(zhí)行env.py -q就能退出任意一個 virtualenv丑孩。
Winpdb 進行可視化調(diào)試
如果你使用的PyDev的話那么用其自帶的斷點調(diào)試應(yīng)該就可以了冀宴。Winpdb則是為用其他簡單編輯器進行 Python 開發(fā)的用戶提供一個熟悉的調(diào)試環(huán)境。Winpdb不出意料的也在 Python(x, y)當(dāng)中温学。所以如果裝上 Python(x, y) 你可以不斷發(fā)掘里面附帶的優(yōu)秀工具略贮。使用方法很簡單,假設(shè)程序名為 foo.py仗岖,那么在命令行中輸入:
winpdb foo.py
之后會彈出窗口逃延,也就是一個大家都熟悉的 debug 圖形界面。需要注意的是這里需要點擊想要設(shè)置斷點的行轧拄,點擊 F9 設(shè)置斷點揽祥,然后該行底色會變?yōu)榧t色,如下圖所示檩电。
編碼問題
作為中文用戶拄丰,初學(xué) Python 最容易碰到的問題估計就是編碼問題了府树。明明英文的都可以用到中文的時候就要出問題,而且出錯信息難以理解料按,想要解決問題又不知道從何開始奄侠。幸運的是編碼問題通過預(yù)防性的措施是很好避免的。下面從幾個方面來講講 Python 中處理中文及 Unicode 容易碰到的問題载矿。
Unicode 編碼基礎(chǔ)
這里非常簡單的講一下編碼知識垄潮,此部分表述可能不太準確,如果你對 Unicode 更為了解的話請聯(lián)系我?guī)兔m正闷盔。
你可以想象 Unicode 是一個很大的表弯洗,里面有著世界上所有的文字的個體,如英文中的字母馁筐,中文的漢字涂召。事實上 Unicode 標準中每一個字都有一個唯一對應(yīng)的編號,好比說 '中'字 對應(yīng)十六進制 0x4E2D敏沉,而字母 'a' 對應(yīng)的是十六進制 0x0061果正。這個編號是由Unicode Consortium這個組織來確定的。 如果說用這個編碼來對應(yīng)字符來用于表示字符盟迟,理論上是可以的秋泳,這樣的話就是每一個數(shù)字編號能對應(yīng)一個字符。
而實際情況中攒菠,不是每篇文章都用得到世界上所有的字符迫皱。譬如一篇英文文章就只有英文字母加上一些符號,用 Unicode 來進行存儲的話每個字符要浪費太多的空間辖众。所以就有各種類型的編碼產(chǎn)生卓起。編碼我們這里可以理解就是將一部分的 Unicode (比如說所有的中文,或者所有的日文)字符凹炸,以某種方式確定另外一個符號來代表他戏阅。中文常用編碼有 UTF8 和 GBK,仍然以 '中'字 為例啤它, UTF8 編碼將對應(yīng) '中'字 的 Unicode 編號0x4E2D拆成三個的編號的組合奕筐,[0xE4, 0xB8, 0xAD],只有這幾個連在一起的時候才會被作為一個 '中'字 顯示出來变骡;作為對比离赫,GBK 編碼將 '中'字 對應(yīng)的 Unicode 編號0x4E2D編碼成為兩個編號的組合[0xD6, 0xD0],在 GBK 編碼環(huán)境下只有這兩個編號一起時塌碌,才會顯示為 '中'字渊胸。
上面的例子中,如果把 UTF8 編碼后的[0xE4, 0xB8, 0xAD]放到 GBK 環(huán)境下來顯示會怎樣台妆?這幾個編號跟 '中'字 在 GBK 下的編碼[0xD6, 0xD0]蹬刷,不同瓢捉,則顯然不會顯示為 '中'字频丘。這三個字符會跟排在其前后的字符一起办成,按照 GBK 的編碼規(guī)則找有沒有對應(yīng)的字符。結(jié)果有可能顯示出一個毫不相關(guān)的字符搂漠,有時候為符號或者干脆不顯示迂卢,這種情況就算產(chǎn)生了亂碼。
Python 2.x 中的 String 與 Unicode
在 Python 2.x 中是有兩種字串符相關(guān)類型的桐汤,分別為 String 和 Unicode而克,兩者提供的接口非常類似,有時候又能自動轉(zhuǎn)換怔毛,蠻容易誤導(dǎo)人的员萍。在 Python 3 中 這兩個類型分別用 Bytes 和 String 替代了。這個名字更能說明兩者的本質(zhì):Python 2.x 中的String 中存儲的是沒有編碼信息的字節(jié)序列拣度,也就是說 String 中存儲的是已經(jīng)編碼過后的序列碎绎,但他并不知道自身是用的哪種編碼。相反的Unicode 中存儲的是記載了編碼的字串信息抗果,其中存儲的就是相應(yīng)字符的 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)
前面兩行后面會解釋到日麸,就是限定運行環(huán)境以及該腳本文件的編碼格式。此腳本在這里可以下載逮光,如果你要自己寫的話請務(wù)必確保腳本的編碼是 utf8 而不是別的代箭。在 Windows 下的運行結(jié)果在這里,我覺得正好能說明問題:
C:\SHARED\Dev\scripts>encoding.py
榪
這也
12
5
這里需要說明涕刚,我們的程序是 UTF8 編碼嗡综,主要意義是該程序中的所有直接寫出來的字串符(用"", ''括起來的字串符)是運用 UTF8 格式編碼的;然而 Windows 下的命令行是 GBK 環(huán)境副女。這里strs是一個String蛤高。事實上在 Python 2.x 中直接寫在程序中的字串符,其類型都是String(這里不考慮 string literal)碑幅。我們先直接輸出strs[0:2]戴陡,得到的是一個亂碼字符(這個字符只是碰巧湊成是一個字)。如上面說的沟涨,String中存儲的是沒有編碼信息的字串序列恤批,這里就是將strs中前兩個編號取出并嘗試顯示。由于命令行環(huán)境為 GBK 編碼裹赴,這里對應(yīng)的字碰巧湊成了一個字喜庞,但是跟原本的字沒有任何關(guān)系诀浪。
unis是由一個String調(diào)用decode()方法得到,這正是在 Python 2.x 中取得Unicode的最基本的方式延都。由于String并不知道它本身是由什么編碼格式來進行的編碼雷猪,這里是我們的責(zé)任來確定他原來是用哪種編碼方式進行編碼。我們知道代碼中的編碼格式是 UTF8晰房,所以我們可以用調(diào)用String的decode()方法來進行反編碼求摇,也就是解碼, 把字串符從某種編碼后的格式轉(zhuǎn)換為其唯一對應(yīng)的 Unicode 編號殊者。unis為解碼獲得的結(jié)果与境,其在 Python 2.x 中對應(yīng)類型就是Unicode,其中存儲的就是 每個字符對應(yīng)的 Unicode 編號猖吴。
我們嘗試輸出unis的前兩個字符摔刁,在這里我們調(diào)用了Unicode的encode()方法。這就是編碼的過程海蔽。我們知道 Windows 命令行下的編碼是 GBK共屈,只有采用 GBK 編碼的字符才能正確顯示。所以在這里我們通過調(diào)用Unicode的encode()方法准潭,將unis中存儲的 Unicode 編號 按照 GBK 的規(guī)則來進行編碼趁俊,并輸出到屏幕上。這里我們看到這里正確的顯示了unis中的前兩個字符刑然。要注意的是在命令行中直接printUnicode的話 Python 會自動根據(jù)當(dāng)前環(huán)境進行編碼后再顯示寺擂,但這樣掩蓋了兩者的區(qū)別。建議總是手動調(diào)用encode和decode方法泼掠,這樣自己也會清楚一些怔软。
后面兩者長度的差別也是佐證我們之前的例子。strs中存儲的是 UTF8 編碼后的編號序列择镇,上面看到一個中文字符在 UTF8 編碼后變成三個連續(xù)的挡逼,所以strs長度為 3x4 = 12。你可以想象strs中存放的并不是中文腻豌,而是一系列沒有意義的比特序列家坎;而unis中存儲的是對應(yīng)的中文的 Unicode 編碼。我們知道每一個字符對應(yīng)一個編號吝梅,所以五個字對應(yīng)五個編號虱疏,長度為 5。
避免苏携,和解決編碼產(chǎn)生的問題
了解了 Python Unicode 編碼解碼的這些概念后做瞪,我們來看看如何盡量的避免遇到讓人煩心的編碼問題。
首先如果你的代碼中有中文,那么一定要務(wù)必聲明代碼的編碼格式装蓬。根據(jù)PEP-0263中的介紹著拭,在程序的最開始加上以下兩行注釋就能確定編碼:
#!/usr/bin/python
# -*- coding: utf-8 -*-
其中utf-8就是指定的編碼格式。事實上你應(yīng)該總是使用 UTF8 作為你 Python 程序的編碼格式牍帚,因為未來的 Python 3 所有文件都將默認以 UTF8 編碼儡遮。另外除了聲明,你必須確定你用來編輯 Python 程序的編輯器是不是真的以 UTF8 編碼來存儲文件履羞。
之后就是養(yǎng)成關(guān)于編碼解碼的好習(xí)慣峦萎。當(dāng)你的程序有String作為輸入時,應(yīng)該盡早的將其轉(zhuǎn)換為Unicode忆首,再在程序中進行處理。再輸出的時候被环,也要盡可能玩糙及,直到最后輸出的時刻才將Unicode編碼為所需編碼格式的String進行輸出。同樣的你必須保持你程序內(nèi)部所有參與運算的字串都是Unicode格式筛欢。很多著名的 Python 庫例如django就是采用的這種方式浸锨,效果也蠻好。千萬不要依賴 Python 自己進行兩者之間的轉(zhuǎn)換版姑,也不要將String和Unicode放在一起運算柱搜,這些行為一方面十分容易引起錯誤,另一方面在 Python 3 中已經(jīng)無法再現(xiàn)剥险。
雖說確定String的編碼格式是程序員的責(zé)任聪蘸,但有時候你真的不知道有些字串符到底是什么編碼的。這里有一個神奇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 直接報錯,多半是字串經(jīng)過多次錯誤編碼解碼壤短,要從別的地方找辦法解決問題设拟。
在處理包含漢字的文本文件時,一個很常見的問題就是有時候會碰到帶有 UTFBOM的文件久脯。這個簡單講就是文件頭幾個字節(jié)是用來表示文件是大端還是小端表示纳胧。在實際中用的很少,而且會帶來很頭疼的問題桶现。有時候你確定你有一個文件是 UTF8 編碼的躲雅,但讀進來頭幾個字節(jié)就出錯,那么十有八九就是這個的問題骡和。Python 在讀取文件時仍然是所有字節(jié)順序讀進來相赁,不會透明的處理這個東西相寇。所以要么你可以用編輯器來把文件另存為無 BOM 的,要么在 Python 中做處理钮科。在標準庫中有codec里面提供了相關(guān)功能:
import codecs
s = f.read(3)
if s == codecs.BOM_UTF8:
print "BOM detected"
這樣可以簡單檢測 BOM 是否存在唤衫,剩下的部分就要你自己發(fā)揮了。
如果上面的介紹還不能讓你理解 Unicode 的概念绵脯,這里還有幾篇關(guān)于這個問題的文章:
介紹 Unicode 的兩篇文章1,2佳励。關(guān)于 Unicode 有更為詳細的解釋。
Unicode In Python, Completely Demystified特別針對 Python 下的 Unicode 處理進行詳細的講解蛆挫。
其他
除了上面幾個重要的問題之外赃承,剩下的資源。
Vim Python開發(fā) 相關(guān)資源
事實上我現(xiàn)在自己是在用 Vim 寫 Python悴侵,感覺也蠻不錯瞧剖。以下是相關(guān)資源。
UltimateVimPythonSetup比較新的一個專門針對 Python 的 Vim 配置文件可免。
Vim as Python IDE只要搜 Python 和 Vim 就一定會找到這一篇文章抓于。
vimcolorschemetest所有的Vim 配色方案都在集結(jié)在這里。
Python 相關(guān) Vim 插件
pythoncomplete.vim按上面的介紹配置一下浇借,在自動輸入的時候按Ctrl-X, Ctrl-O就有很強力的自動補全了捉撮。
python.vim加強語法的高亮。
pyflakes.vim很棒的語法檢查妇垢,分析你的語法看避免低級錯誤巾遭。注意這個在Vim7.2下才有用, 如果是7.1則一點效果都沒有...
其他相關(guān)資源
這個把Python(x,y)里面所有的模塊基本上都講了一遍修己,我覺得外國人肯定都希望這個有個英文版的恢总。
這個名字看起來像個Python庫(其實它還真的是一個...),但他總體來說其實是一份文檔睬愤, "Python每周一個模塊"片仿。作者持續(xù)幾年每周介紹一個Python標準庫中的庫。你可以把他看做是一個Python標準庫文檔的一個很棒的補充尤辱,當(dāng)你看標準庫中的介紹看的云里霧里的時候砂豌,不妨來這邊找找相應(yīng)的介紹。因為這里的例子給的很全光督,而且基本上你用的到的偏門的庫這里都有介紹哦阳距。另外一個好消息是PyMOTW有一份很棒中文翻譯版。
reddit.com/r/python和python.org planet
文/yido(簡書作者)
原文鏈接:http://www.reibang.com/p/aee3c903e353
著作權(quán)歸作者所有结借,轉(zhuǎn)載請聯(lián)系作者獲得授權(quán)筐摘,并標注“簡書作者”。