IPython,讓Python顯得友好十倍的外套——windows XP/Win7安裝詳解

IPython,讓Python顯得友好十倍的外套——windows XP/Win7安裝詳解

前言

學習python,官方版本其實足夠了。但是如果追求更好的開發體驗,耐得住不厭其煩地折騰。那么我可以負責任的告訴你:IPython是我認為的唯一顯著好于原版python的工具。

整理了《Python 二三事》:http://pre-sence.com/archives/python-intro ? 《Python 四五事》:http://pre-sence.com/archives/python-misc 并加入安裝IPython部分。

寫這篇隨筆的原因是:忽然醒悟之前我安裝IPython折騰許久不成功可能是我未能想起pip或easy_install這兩個python的上帝工具。參考:Python包管理工具pip與easy_install

個人經驗總結:IPython,是學習python的利器,是讓Python顯得友好十倍的外套,是我唯一的強烈推薦。

安裝IPython

任何Linux發行版對編程者都十分友好

Ubuntu為例: sudo apt-get install ipython

windows環境:

1、下載ez_setup.py,右擊左邊鏈接,另存為,使用python ez_setup.py運行,或直接雙擊。

2、步驟1成功后,cmd下輸入命令easy_install -h可以測試,正常反應說明已經可以使用easy_install了。

3、cmd下輸入easy_install pip安裝pip,這是因為pip正是easy_install的下一代,比easy_install好用。

4、步驟3成功后,pip install ipython。

5、如果步驟4不行,退一步,使用easy_install ipython安裝。

運行IPython

cmd提示符下,輸入ipython運行就可以使用除了原python外,IPython多出來的貼心的“I”了。

退出IPython

與python一樣也是輸入exit

Python實用技巧:

1、關于 "_" 字符使用

在 Python shell 下 _ 總是被賦予之前最后一個表達式的值(注:@pythonwood)。這里看個例子應該就能清楚:

>>>importstring

>>> string.letters

'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'

>>>print_

abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ

>>>2014

2014

>>> v=_

>>> v

2014

舉個實際的例子,比如你在調試時讀文件的時候直接進行 f.read() ,你看了看發現輸出結果很有意思,想要對它進行進一步處理,但發現讀的時候忘記賦值了。以往你只能嘆嘆氣重新開文件再讀一次,現在你只要執行 result = _,把 _ 附到另外一個變量就可以了。

2、python -m

相信很多人應該用過這個東西,Python 很多標準庫都提供這樣的調用方式來實現一些簡單的命令行功能。Python 3 現在自帶 pip。比如我們想使用 Python 3 的 pip 來安裝別的庫,我們可以這樣:

py -3 -m pip install bottle

跟你預料的一樣,這樣就可以了。當然你可以用個 .bat 文件來把這些包裹起來并放在 Path 上,一個簡單的例子,把下面的內容寫到一個叫 pip3.bat 的文件里:

@echo off

py -3 -m pip %*

并放到 Path 上,就可以方便調用了。其中 %* 負責傳遞所有的命令行參數。

實際上 python -m 可以用的東西還真的挺多,這里給出一個不完全的列表:

######################################################

# 最強功能

######################################################

# 局域網共享,宿舍中任意一臺筆記本都可以瞬間變身web資源共享服務器

# 命令ipconfig可以看到局域網ip地址,一般是192,172這些開頭的。

# 使用本機80端口,可任意設置。只共享當前運行目錄。

#

python-m SimpleHTTPServer80

#

# 本機任意瀏覽器輸入http://localhosthttp://127.0.0.1可以訪問。

# (80端口瀏覽器默認的,不需輸入)甚至在地址欄直接輸入localhost即可。

# 局域網,(宿舍)任意電腦輸入上面所說192或172等開頭的IP地址即可訪問。

######################################################

# 縮進輸出 JSON

echo {"hey":"kid"} | python-m json.tool

# 簡單的執行時間測量

python-m timeit [ix*ixforixinrange(100)]

# 簡單的 Profiling

python-m cProfile myscript.py

# 比較兩個文件夾的區別

python-m filecmp path/to/a path/to/b

# base64 轉換

echo foo bar | python-m base64

# 調用默認瀏覽器打開一個新標簽頁

python-m webbrowser-t http://google.com

# 生成程序文檔

python-m pydoc myscript.py

# 類似 nose 的自動搜索 unittest

python-m unittest discover

# 調用 pdb 執行代碼

python-m pdb myscript.py

IPython實用技巧:

1、Tab自動補全,一種是簡單的關鍵字補全,另外一種是對象的方法和屬性補全。

作為例子,我們先引入sys模塊,之后再輸入sys.(注意有個點),此時按下 tab 鍵,IPython 會列出所有 sys 模塊下的方法和屬性。

接著上面的例子,我們輸入sys?,這樣會顯示出sys模塊的 docstring及相關信息。很多時候這個也是很方便的功能。

2、IPython 還有強大之處很大部分還體現在它的magic function中。它是指的在 IPython 環境下執行以%開頭的一些命令來對 IPython 進行一些設定或者執行某些功能。在 IPython 中輸入%lsmagic就能列出所有的magic functions。在這里簡單介紹下幾個比較有意思的,你也可以自己通過查看文檔來找找有哪些你特別用的到得。

之前看到能用?來查詢函數的文檔,對于 magic function 也是如此。比如%run?。

!cd ..在命令前面加上!則它會被作為命令行命令執行,這樣你就不用退出 IPython 來進行命令行操作。

%run foo.py在當前環境下直接執行foo.py,效果跟命令行下調用ipython foo.py相同。

%time foo.bar()跟timeit decorator作用相同,進行簡單的 profile。

%hist能顯示之前輸入過的命令的歷史,同時你可以用In[]來訪問之前的命令。比如%exec In[10]就能執行列表中第十行。

%rep類似上面的_變量,但是是以字串的形式返回

最后,如果%automagic是打開的狀態的話,所有 magic function 不需要在前面加%就能正確調用。

在當前 IPython 版本中還有一個由于安全原因沒有默認引入的%autoreload,它的作用是在可以自動重新載入你調用的函數,以及其相關模塊。接觸過django的同學對這個應該比較熟悉,在 IPython 中的效果就是,當你在調試一個一直在反復改動的函數時,你可以開啟這個功能保證每次調用都會重新讀取最新的版本,讓你在源碼中的改動馬上生效。在 IPython 中執行

importipy_autoreload

%%autoreload2

這樣 IPython 會對所有的模塊都進行 autoreload。你可以通過執行%autoreload?來查詢它的文檔來進行進一步設定。如果你希望 IPython 每次啟動自動載入次功能,那么可以通過配置 ipythonrc (在 Windows 下可以在C:\Users\\_ipython\ipythonrc.ini找到) 來進行相關設置。

3、還有一個很神奇的功能。如果你的程序是由命令行開始執行的,即在命令行下輸入python foo.py(大部分 Python 程序都是),那么你還可以利用 IPython 在你的程序任意地方進行斷點調試!

在你程序中任意地方,加入如下語句:

fromIPython.ShellimportIPShellEmbed

IPShellEmbed([])()

注意:最近 IPython 發布了0.11 版本,各方面變化都非常大,API 也經過了重新設計。如果你使用的是 0.11 那么上面兩行對應的是這樣的:

fromIPythonimportembed

embed()

再和平常一樣運行你的程序,你會發現在程序運行到插入語句的地方時,會轉到 IPython 環境下。你可以試試運行些指令,就會發現此刻 IPython 的環境就是在程序的那個位置。你可以逐個瀏覽當前狀態下的各個變量,調用各種函數,輸出你感興趣的值來幫助調試。之后你可以照常退出 IPython,然后程序會繼續運行下去,自然地你在當時 IPython 下執行的語句也會對程序接下來的運行造成影響。

這個方法我實在這里看 到的。想象一下,這樣做就像讓高速運轉的程序暫停下來,你再對運行中的程序進行檢查和修改,之后再讓他繼續運行下去。這里舉一個例子,比如編寫網頁 bot ,你在每取回一個頁面后你都得看看它的內容,再嘗試如何處理他獲得下一個頁面的地址。運用這個技巧,你可以在取回頁面后讓程序中斷,再那里實驗各種處理方 法,在找到正確的處理方式后寫回到你的代碼中,再進行下一步。這種工作流程只有像 Python 這種動態語言才可以做到。

4、一個實際的例子

這里以一個簡單的例子來講解一下是怎樣的一個情況。我們要寫一個可以將簡單的數據表達式,類似1 + (2 - 3) * 456解析成樹的Pratt Parser。首先我們需要一個 lexer 把每個 token 解析出來,那么最開始的代碼就是:

# simple math expression parser

deflexer(s):

'''token generator, yields a list of tokens'''

yields

if__name__=='__main__':

fortokeninlexer("1 + (2 - 3) * 456"):

printtoken

明顯這個沒有任何意義,但現在程序已經有足夠的東西能夠跑起來。我們把這個程序存為expr.py,開啟一個命令行窗口,運行ipython然后像這樣執行它:

$ ipython

IPython0.13.1--An enhanced Interactive Python.

?-> Introductionandoverview of IPython's features.

...

In [1]: run expr.py

1+(2-3)*456

在 IPython 里面用run跑的好處有很多,首先是你在程序執行完畢后整個程序的狀態,比如最后全局變量的值,你寫的函數這些你都是可以隨便執行的!同樣的你可以在 IPython 里面保存一些用來測試的常量,每次用run跑的話新的程序會被重新載入,你可以這樣方便的測試每個函數,有一個非常動態的環境來調試你的程序:

In [2]:printtoken# 注意這里 token 就是 __main__ 里面的那個 token 的值

1+(2-3)*456

In [3]:printlist(lexer('1+2+3'))# 可以運行你寫的函數

['1+2+3']

然后按照之前的想法,我們嘗試把這個 lexer 寫出來。在這個過程中,IPython 可以用來查看函數的文檔,測試如何調用某些函數,看看返回值是什么樣子等等,還是跟上面的說的一樣,我們有一個動態的環境可以真真正正的執行程序,你可以 在把代碼寫到你珍貴的主程序之前就有機會運行它,這樣你可以更確認你的代碼能正常工作:

In [4]: s="foo"# 忘記判斷字符串是數字的函數的名字了,用一個字符串試試看

In [5]: s.is# 開頭大概是 is,這里按下 tab 鍵 IPython 會幫我們補全

s.isalnum? s.isalpha? s.isdigit? s.islower? s.isspace? s.istitle

In [6]: s.isdigit?# 結果是 isdigit,在表達式后加上問號并回車查看文檔

Type:?????? builtin_function_or_method

String Form:

Docstring:

S.isdigit()->bool

ReturnTrueifallcharactersinS are digits

andthereisat least one characterinS,Falseotherwise.

In [8]: s.isdigit()# 調用試試看

Out[8]:False

In [9]:'f'in'foo'# 試試字符串能不能用 in 來判斷

Out[9]:True

確認了各個步驟以后,我們把 lexer 的代碼填起來。我們為了節省縱向的空間我們把很多東西寫在一行里面:

# simple math expression parser (broken lexer)

deflexer(s):

'''token generator'''

ix=0

whileix

ifs[ix].isspace(): ix+=1

ifs[ix]in"+-*/()":

yields[ix]; ix+=1

ifs[ix].isdigit():

jx=ix+1

whilejx

yields[ix:jx]; ix=jx

else:

raiseException("invalid char at %d: '%s'"%(ix, s[ix]))

yield""

if__name__=='__main__':

printlist(lexer("1 + (2 - 3) * 456"))

看起來不錯,我們還是在 IPython 里執行試試,結果發現程序拋出了一個異常:

In [6]: run expr.py

------------------------------------------------------------------

Exception?????????????????????? Traceback (most recent call last)

py/expr.pyin()

if__name__=='__main__':

--->20printlist(lexer("1 + (2 - 3) * 456"))

py/expr.pyinlexer(s)

yields[ix:jx]; ix=jx

else:

--->raiseException("invalid character at ...))

yield""

Exception: invalid character at3:' '

嗯?好像程序里已經處理了空格的情況。怎么會這樣?不知道你碰到異常的時候一般都怎么辦。你可能會選擇到處添加print,用 IDE 斷點調試。其實這種情況用pdb是很明智的選擇,在 IPython 里我們可以非常輕松的使用它。

In [13]: pdb# 開啟 pdb ,這樣在異常的時候我們會自動的 break 到異常處

Automatic pdb calling has been turned ON

In [14]: run expr.py

-----------------------------------------------------------------

Exception: invalid character at3:' '

> py/expr.py(15)lexer()

else:

--->raiseException("invalid char at ...))

yield""

ipdb>printix# 這里我們可以執行任何 Python 的代碼


ipdb> whatis ix# 也可以用 pdb 提供的命令,輸入 help 可以查看所有命令

通過方便的調試和仔細檢查代碼,我們發現是沒有正確的使用elif造成了問題!(我知道這個過程不是太符合情理...)。把代碼里的后面的幾個if都換成elif以后我們發現結果基本上是對的了。我們可以馬上再跑幾個類似的例子,確認不同的輸入是否都有比較好的結果:

In [18]: run expr.py# 這次差不多對了,我們可以試試幾個別的例子

['1','+','(','2','-','3',')','*','456', '']

In [19]:printlist(lexer("1*123*87-2*5"))

['1','*','123','*','87','-','2','*','5', '']

# 跟在 shell 里面一樣,你可以用上下來選取之前的記錄,然后簡單的修改再重新執行。

# 記得每次 run 后你的函數都是最新版本,你可以很簡單的用重復的數據來測試你的函數

# IPython 甚至還實現了 Ctrl+R!自己試試看吧

In [19]:printlist(lexer("1 + two"))

Exception: invalid character at2:'t'...

在一段痛苦的調試之后,我們最終把程序寫出來了。很遺憾程序超出了我預計的長度,就不貼在這里了。后面部分的開發過程跟前面基本還是一樣,總結起來就是:

保持你的程序是一個可以運行并且有意義的狀態,盡可能頻繁的運行。

在 IPython 里查看文檔,嘗試小的程序片段,測試些你不確定的做法,確定之后再把東西添加到你的代碼里。

用不同的參數在 IPython 里測試你正在編寫的函數/class。

當遇到問題的時候,先簡單的用pdb在異常處 break,十有八九都能有些頭緒。

額外的注意事項

這里舉的例子是你所有的開發都是在單個.py文件里的。現實生活中你很有可能會橫跨幾個文件一起修改。請務必注意,在 IPython 里你每次run的時候只有被run的那個文件里的東西會是最后修改的版本,其import的東西如果在期間被修改是不會反應出來的。

這個的原理就跟你在 Python shell 里在修改前修改后重復import某個模塊不會有作用是一樣的,Python 神奇的import機制不會去追蹤其他模塊的修改。你可以手動用reload函數來重新載入,你也可以使用 IPython 的autoreload功能來讓你忽略這個問題。個人來說我沒怎么用過這個功能,IPython 沒有默認開啟它可能也是有些顧慮,請自己評估看看。

另外你應該已經注意到,run的效果基本上就是把你的代碼拷貝進 IPython 里執行一遍。對于沒有__main__的文件,你也可以run,這樣里面定義的函數和 class 就會反映出你的更改。

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

推薦閱讀更多精彩內容