剛開始接觸Python的時候,網上找到的資料基本上上來就是介紹Python語言,很少有對開發環境進行講解的,但如果在學習的過程中不斷練習,這樣效率會更高,所以特意將一個Python的開發環境Spyder自帶的入門教程翻譯出來,希望可以幫助到和我有同樣困惑的你。
個人水平有限,會有翻譯不到位的地方,歡迎批評指正!
Spyder是使用Python編程語言進行科學計算的集成開發環境。它有一個Editor(編輯器)用於編寫代碼,Console(控制台)可以評估代碼並且在任何時候都可以看到運行結果,Variable Explorer(變量管理器)可以查看代碼中定義的變量,還有其他的一些設備可以幫你高效地開發代碼。
本教程由英國南安普頓大學的Hans Fangohr所寫。
使用Spyder的第一步
這部分內容針對Python和Spyder的初學者,如果你覺得太簡單,請繼續學習下一部分內容。
執行一段代碼
-
我們將使用這段代碼作為第一個例子:
# Demo file for Spyder Tutorial # Hans Fangohr, University of Southampton, UK def hello(): """Print "Hello World" and return None""" print("Hello World") # main program starts here hello()
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
-
為了使用這段代碼,請在Spyder的Editor(編輯窗)新建一個文件。將代碼拷貝到文件中,並以hello.py文件名保存該文件。
-
為了執行這段代碼,從菜單中選擇Run > Run(或者按F5鍵),如果有需要請確認Run settings的設置。如果這是第一次運行代碼,你可能會看到如下形式的輸出:
In [1]: runfile('/Users/fangohr/Desktop/hello.py', wdir=r'/Users/fangohr/Desktop') Hello World In [2]:
- 1
- 2
- 3
- 4
這說明你已經成功運行了第一個Python程序。
注意:
runfile旁邊顯示的具體路徑取決於你剛剛保存文件的位置。
使用IPython Console
我們推薦您使用IPython Console,因為它比標准的Python Console的功能更多,並且建議您將它設置為默認控制台。
在執行代碼的過程中到底發生了什么?
-
Python逐行讀取Editor中的代碼,並且它會自動忽略注釋(即以#符號開頭的行)。
-
當遇到def關鍵字,Python知道在這里定義了一個函數。在def hello():之后的所有縮進行都是函數體。
注意:這個函數對象僅僅只是在文件的這個位置被定義了,並沒有被調用(或者執行)。
-
當Python遇到從最左邊的列開始寫的命令(除了def…和其他一些關鍵字),它將馬上執行這些命令。在hello.py文件中只在hello()的這一行才正真調用名為hello的函數。
如果你在代碼中注釋掉或者刪除hello()這一行,再次執行整個文件(按F5鍵或者選擇 Run > Run),將不會打印任何內容,因為函數hello只被定義了,但沒有被調用。
通過使用IPython Console,現在你應該知道Spyder中Editor窗口中的Python代碼是如何執行的了。
如果你剛開始學習Python,現在最好返回到課本或者課程中練習更多的程序實例。
下一部分內容將詳細介紹如何在IPython Console中執行Editor窗口中的代碼段,然后更新Editor中的部分定義。這是一種更先進的技術,並且非常有用。(你可能對執行被分隔符隔開的代碼塊(也稱為“cells”)也感興趣,可以查看——功能快捷鍵)。
調用console中的函數
你一旦執行了hello.py文件,函數對象hello就被定義了,並且IPython console也知道了它的存在。因此,我們可以用如下方式在console中調用函數:
-
在console中寫入hello()(靠近In[?],?可以是任意正整數),然后按下Enter鍵。
你應該發現hello()函數又被執行了一遍,Hello World又被打印了一次。在console中調 用函數和輸出的形式應該如下:In [ ]: hello() Hello World
- 1
- 2
-
你能發現它和執行整個代碼之間的區別嗎?
當你執行整個代碼時,Python會遍歷整個文件,創建一個hello函數對象(覆蓋之間的 對象),當到達hello()這一行就調用這個函數。
如果我們在console中調用hello(),我們只是調用了之前執行整個hello.py文件在IPython console中定義的函數對象hello。
這些概念在多次練習或者處理更大一些的代碼實例后會更加清楚。在稍后的階段中你可能還會返回此教程。
查看定義在console中的對象
-
Python提供了一個函數,它可以顯示console中當前命名空間中所有已知的對象。它就是dir():當你在console中寫入dir(),你將得到一個對象列表。現在忽略所有以下划線開始的。你能看見hello在列表中嗎?
注意:
如果你得到了一個定義對象的長列表,那么Spyder可能已經為你做了一些方便的導入。 為了強調這一點,你需要:- 重啟命名空間
- 按F5鍵再次執行hello.py
按上文介紹的步驟運行dir()。
-
一旦一個對象在當前命名空間中可見(例如本例中的hello),我們可以使用help函數了解這個對象:在console提示區寫入help(hello),你應該可以看到如下的輸出:
In [ ]: help(hello) Help on function hello in module __main__: hello() Print "Hello World" and return None
- 1
- 2
- 3
- 4
- 5
Python從哪獲取的信息呢?其中一些信息(例如輸入的參數個數和變量名稱,這里我們沒有輸入參數)Python可以通過檢查對象獲得,另外一些信息源自於提供給函數對象hello的文檔字符串。文檔字符串就是緊挨着def hello():的下一行字符串。
這些字符串很特殊,他們被稱為docstring,是documentation strings的縮寫。它們通常有好幾行,並且被三個單引號( ’ ’ ’ )或者三個雙引號(“ ” ” )封裝起來。
- Spyder開發環境同樣提供了Help窗口,通常默認位於右上角。
當光標在一個對象名字之上,按下CTRL+i(在MAC中按下CMD+i),我們可以獲得同使用help(hello)一樣的信息。
這在console和Editor中都起作用。
更新對象
簡單策略:重新執行整個程序
-
在Editor窗口,修改函數hello使其輸出Good Bye World而不是Hello World。
-
按F5鍵執行整個程序,然后檢查當前程序的輸出:
Good Bye World
- 1
當你按下F5鍵時發生了什么?其實,Python遍歷的整個hello.py文件,創建了一個新的函數對象hello(覆蓋了之前的函數對象hello),然后執行了整個函數。
我們看一下細節
我們需要從一個定義清晰的情形開始。為了做到這一點,請你將函數hello()改回輸出Hello World的情況,然后按F5鍵執行整個程序,檢查輸出應該是Hello World。
-
在console命令提示區調用hello()函數。你會看到輸出Hello World。
-
現在在editor窗口改變函數使其打印Laters World,然后保存文件,但不要執行程序(不按F5鍵)。
-
在console中調用hello()函數。你會看到輸出是Hello World,如下:
In [ ]: hello() Hello World
- 1
- 2
為什么會這樣?因為console中的hello函數對象是打印Hello World的舊的函數對象。因此,因此我們在editor中改變hello.py(用Laters World代替了Hello World)文件並不會影響之前在console中創建的對象。
有兩種方法可以更新hello函數的版本:
-
方法一:按F5鍵重新執行整個hello.py文件,這一操作會生成一個新的hello函數對象,並覆蓋舊的。你會發現,當你按下F5鍵,在console命令提示區調用hello(),會輸出新的文本Laters World。
-
方法二:選中你改變的區域,在這個例子中是整個hello函數,從def hello():開始到print(“Laters World”)結束,然后選擇Run > Run selections。
這樣就會更新console中的hello對象,而不用重新執行整個hello.py文件:In [ ]: def hello(): ...: """Print "Hello World" and return None""" ...: print("Laters world") ...:
- 1
- 2
- 3
- 4
如果現在寫入hello(),我們會看到更新后的輸出:
In [ ]: hello() Laters world
- 1
- 2
在console中通過執行部分代碼(上述例子中我們升級了函數對象hello)來升級一些對象的能,對於將來開發和調試更復雜的代碼非常有用,也會節省在console中創建對象或數據的時間。例如,只修改我們真正想要調試的函數(或者類/對象),我們可以繼續使用當前console中定義的數據和其他對象。
Python初學者的第一步
對於Python編程教學和學習,我們推薦使用IPython console而不是Python console,這在科學Python社區被認為是事實上的標准。
轉換到IPython console
如果你已經有一個激活的IPython console,那么你可忽略這部分內容,只要用鼠標點擊“IPython console”就使它可見了。
在console窗口中(默認位於右下角),在默認情況下用3個大於號最為提示,如>>>。這表示我們使用的是普通的Python console(Spyder新增了一些功能)。
然而我們更喜歡使用交互式的Python console(Interactive Python console),即IPython console。因此,選擇Console > Open an IPython Console。
你可以看到在console窗口中產生了一個新的命令窗,IPython 的提示區是In [ 1 ]:
重置命名空間
命名空間(在任何給定時間內在console中定義的對象集合)在IPython中可以使用%reset命令清除。輸入%reset然后按下enter鍵,用y確認:
In [1]: %reset Once deleted, variables cannot be recovered. Proceed (y/[n])? y In [2]:
- 1
- 2
- 3
- 4
- 5
這就可以了。
我們對它進行更深一層的討論,倘若你不感興趣,也可以跳過這部分內容:使用%reset命令之后,在當前會話中只有少部分對象在命名空間中。我們可以使用dir()把他們都列出來:
In [2]: dir() Out[2]: ['In', 'Out', '__builtin__', '__builtins__', '__name__', '_dh', '_i', '_i2', '_ih', '_ii', '_iii', '_oh', '_sh', 'exit', 'get_ipython', 'help', 'quit']
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
最后,如果你想在使用reset命令時跳過確認步驟,你可以使用%reset -f命令。
遵守PEP8規則
除了由Pyhton編程語言執行的語法之外,關於源代碼的布局還有其他約定,特別是Style Guide for Python source code即大家所熟知的“PEP8”。遵循這一規則,盡可能寫出相同風格的代碼,這樣,對於代碼的作者和用戶就更容易讀和調試。
你需要修改Spyder的設置,如果觸犯了PEP8的編碼規則,就會自動警告。
參數設置
參數在哪配置
很多Spyder的行為都可以通過配置參數實現。而它們在菜單的位置取決於你是用的操作系統:
-
在Windows和linux系統,使用Tools > Preferences
-
在Mac OS中,使用Python/spyder > Preferences
設置PEP8規則檢測警告
Preferences > Editor > Code Introspection/Analysis,然后勾選Style analysis(PEP8)。
激活sympy模式
通過Preferences > IPython console > Advanced Settings > Use symbolic math激活IPython的sympy模式,這個模式由sympy模塊提供。Spyder中的這一模式提供了非常好的渲染過的數學上的輸出(LaTeX風格),並匯報它完成了什么。在IPython console啟動時自動導入一些sympy對象。
These commands were executed:
>>> from __future__ import division >>> from sympy import * >>> x, y, z, t = symbols('x y z t') >>> k, m, n = symbols('k m n', integer=True) >>> f, g, h = symbols('f g h', cls=Function)
- 1
- 2
- 3
- 4
- 5
- 6
我們可以使用變量x,y:
方便的快捷方式
-
F5執行當前文件。
-
Tab鍵自動補全命令、函數名、變量名、Console(Python和IPython)和Editor中的方法名。這個特點也很有用,將來你可能會頻繁地使用。現在你就可以嘗試一下這一功能。假設你定義了一個變量:
mylongvariablename = 42
假設我們需要寫代碼計算mylongvariablename + 100,我們只需要輸入 my 然后按Tab鍵。如果這個變量名是唯一的,在光標位置會自動補齊變量名,然后再繼續輸入 + 100。如果以字母my開頭的變量名不是唯一的,按下Tab鍵之后會列出所有以my開頭的變量名以供選擇,之后可以使用上下鍵選擇,也可以輸入更多的字母匹配。 -
Ctrl+Enter執行當前cell(在菜單中Run > Run Cell)。Cell是以#%%開頭的兩行之間的代碼。
-
Shift+Enter執行當前cell並將光標移到下一個cell(菜單中選擇Run > Run cell and advance)。
Cells可實現將大的文件或代碼段以小單元執行。 -
Alt+把當前行向上移一行。如果很多行被選中,它們將被一起移動。 Alt+則是相對應的將某(些)行向下移。
-
Ctrl+鼠標左鍵 在一個函數/方法名上使用Ctrl+鼠標左鍵,打開一個新的editor窗口顯示這個函數的定義。
-
Ctrl + +(Cmd + +在MacOS),將增大Editor窗口的字體,Ctrl + -則相反。在IPython窗口中也適用。
Help或者python console窗口中的字體則通過Preferences > Help設置。
Variable Explorer則沒辦法改變。 -
Ctrl + s(Cmd + s在MacOS上)保存當前Editor窗的文件。這還會在編輯器的左欄中強制更新各種警告三角形(否則它們默認2到3秒更新一次)。
-
Ctrl + s(Cmd + s在MacOS上)在IPython console窗將會把當前IPython會話以HTML文件保存,包括任何顯示在命令行的參數。這樣可以快速記錄在會話中完成了什么。
(但是不能將這個HTML 文件再次加載到會話中,如果你需要這樣的功能,請查看 IPython Notebook。) -
Ctrl + i(Cmd + i在MacOS上),當光標在一個對象上時使用,將在help窗口顯示這個對象的文檔。
執行設置
這些設置定義當我們選擇Run > Run或者按了F5鍵Editor中的代碼如何執行的。
默認情況下,當我們第一次執行一個文件時設置會出現。如果我們想改變設置,可以選擇Run > Configure或者按F6找到它們。
對於console有3種方法可用,我們將討論其中兩種。我們假設在Editor中有如下形式的hello.py程序:
def hello(name): """Given an object 'name', print 'Hello ' and the object.""" print("Hello {}".format(name)) i = 42 if __name__ == "__main__": hello(i)
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
在當前Python或者IPython console中執行
這是一個建議,通常也是一個很好的選擇。
存在的對象I(執行代碼之后)
選擇Run > Configure下的Execute in current Python or IPython console這一設置,意味着:
1.當完全執行hello.py,我們可以和執行代碼的console交互,並且我們可以很方便的使用IPython console做到這一點。
2.我們可以檢查對象,也可以和執行代碼創建的對象交互,例如i和hello()。
這種方法對於遞增式的編程、測試和調試都非常有用:我們可以在console的命令提示區直接調用hello()函數,而不用執行整個hello.py文件。
存在的對象II(從代碼執行前開始)
然而,在當前console中執行Editor中的代碼也意味着:
3.其他定義與console會話中的其他(全局)對象對於執行的代碼也是可見的。
這些對象的存在很容被遺忘,對於小量級的代碼也不是必須的。這些對象可能源自於之前執行的代碼,也可能來自console中的交互式工作,又或是源於一些導入(例如from pylab import *,Spyder也可能會自動導入)。
如果無意間依賴於這些對象,控制台命名空間中對象的可見性可能會導致代碼出錯。
實例如下:我們可以想象:
-
運行hello.py文件,變量i在console中就是一個全局變量。
-
編輯hello.py文件,刪除i = 42這一行。
-
再次執行hello.py文件。在這時調用hello(i)依然不會出錯,即使現在的hello.py文件中已經沒有定義i,因為console中之前已經存在變量i了。
這時,我們保存hello.py文件,本想着可以正確執行。但是,在新的(I)Python console會話中執行代碼卻導致錯誤,因為i並沒有被定義。
這一問題的出現是因為代碼使用了一個代碼本身沒有創建的對象(這里是i)。這一問題同樣會影響模塊導入:如果我們在IPython console命令提示區導入了pylab,它對於我們在IPython console會話中執行的代碼就是可見的。
為了學習如何確認我們的代碼並沒有依賴於已經存在的對象,請看“如何雙重檢查你的代碼是獨立正確運行的”這部分內容。
在一個獨立的Python console中運行
在Run > Configure下選擇Execute in new dedicated Python console,在每次運行hello.py程序時都會重新開啟一個新的Python console。它的主要優點在於,在這一模式下我們可以確定在執行代碼時的console中不會有源自於之前調試和執行代碼產生的對象。這樣,每次執行editor中的代碼,python console都是新的。
這一選擇很安全,但是靈活性下降,並且不能使用IPython console。
如何雙重檢查你的代碼是獨立正確運行的
假設你已經選擇 Execute in current Python or IPython console這一選項,你有兩種方法可以確認你的代碼時獨立運行的(例如,代碼不依賴於未定義的變量,未導入的模塊和命令)。
1.從 Execute in current Python or IPython console換到 Execute in new dedicated Python console這一選項,然后再獨立的Python console中運行Editor中的代碼。
另一種方法你也可以選擇。如果你想繼續使用當前的IPython console,你可以
2.使用IPython console的%reset命令,這將會移除所有當前命名空間中的對象(如上述例子中的變量i),然后再執行Editor中的代碼。
建議
我給初學者的建議是使用 Execute in current Python or IPython console,然后選擇IPython console。
一旦你完成了一段代碼,你都可以使用上述的兩種方法確認你的代碼是否獨立運行。
其他需要注意的內容
多文件
如果在Editor中打開了多個文件,窗口頂部文件名對應的標簽從左往右是以字母表順序排列的。
在左側的標簽,有一個圖標,當鼠標移到它上面會顯示Browse tabs。在很多文件打開時,它可以使你能直接跳轉到某一文件。
環境變量
環境變量可以在Python Console窗口中顯示。單擊Options圖標(提示信息就是Options),然后選擇Environment variables。
重置個性化設置
所有個性化設置都可以被重置,調用以–reset結尾的命令行。例如:spyder –reset。
Variable Explorer中的對象
在variable explorer中選擇變量,鼠標右鍵,將會給出進一步分析它們的選項。
鼠標雙擊一個字典對象,將會在一個新的窗口中顯示這個字典。
你同樣可以顯示和編輯數組、列表、數字和字符串。
說明文檔的格式
如果你想為你正開發的代碼添加說明(我們也推薦您為它編寫說明),那就使用被稱為reStructuredText的特殊格式。這種格式需要遵守叫做 Numpydoc standard的標准。
你遵照那些指導,就可以在Spyder中編寫非常漂亮的說明。
例如,為了在Spyder的Help窗口中得到如下展示的average()函數:
你應該以如下形式編輯說明文字:
def average(a, b): """ Given two numbers a and b, return their average value. Parameters ---------- a : number A number b : number Another number Returns ------- res : number The average of a and b, computed using 0.5*(a + b) Example ------- >>> average(5, 10) 7.5 """ return (a + b) * 0.5
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
需要注意的是,這里使用了Parameters關鍵字,並且有下划線。a : number這一行告訴我們參數a是一個數。下一行是補充說明,我們可以給出更加詳細的解釋,這個變量代表什么,它的數據類型應該滿足什么條件等等。
對於其他參數和返回值都可按這個形式編寫。
通常情況下,像展示的那樣給出例子是在好不過的。
調試
逐行執行代碼
如果Python console處於激活狀態,通過Debug > Debug菜單選項或者Ctrl + F5開始Python調試器,如果IPython console處於激活狀態則開啟了IPython調試器。之后,Editor窗口將會高亮將要執行的代碼行,Variable Explorer窗口將顯示當前執行代碼中的變量。(它只顯示變量的數值和數組類型,不會顯示函數或者類對象)。
進入調試模式之后,使用調試工具欄中的Step按鈕,你可以逐行執行代碼:,或者使用快捷方式Ctrl + F10。
你可以查看某一個具體的函數是如何執行的,通過Step into按鈕,或者使用快捷方式Ctrl + F11。
從某一函數中跳出並執行下一行程序則使用Step return按鈕,或者使用快捷方式Ctrl + F12 。
如果你希望在某一具體位置檢查你的程序,則需要在你想要暫停的某一行插入breakpoint,通過按下F12即可實現,你會發現在這一行的旁邊會有一個紅色的點。這時當你按下Continue按鈕,程序執行到這一行就會暫停。
注意:
你同樣可以在console命令窗中使用如下命令控制調試進程:
n 移動到下一行;
s 進入當前語句,如果是一個函數則進入這個函數;
r 執行完當前函數的所有語句並從該函數返回;
p 打印變量的值,例如p x將打印變量x的值。
在調試器的命令行中,你也可以干煸變量的值。例如,為了在IPython調試器命令漢中改變變量x的值,則使用ipdb > x = 42,調試器就會用綁定了42的x。你可以調用這個函數做其他的事。嘗試如下例子:
def demo(x): for i in range(5): print("i={}, x={}".format(i, x)) x = x + 1 demo(0)
- 1
- 2
- 3
- 4
- 5
- 6
如果我們執行它(Run > Run),我們可以看到如下輸出:
i=0, x=0 i=1, x=1 i=2, x=2 i=3, x=3 i=4, x=4
- 1
- 2
- 3
- 4
- 5
現在使用調試器(Debug > Debug)執行代碼,先一直使用Step按鈕,當高亮的行到達demo(0)時使用Step into按鈕查看這個函數。繼續使用Step按鈕執行剩下的代碼行。之后,在調試器命令窗用命令x=10改變x的值。你可以看到在Variable Explore窗中x的值也改變了。你同樣可以看到打印出來的作為函數demo()的一部分的x值的變化。
逐行執行代碼、查看變量的變化、手動修改變量的值,這一調試技能對於理解代碼是如何執行的非常有用。
為了離開調試模式,你可以在命令窗使用exit命令或者在菜單中選擇Debug > Debugging Control > Exit。
當IPython中出現了一個異常如何開啟調試模式
在IPython console中,當一個異常產生之后,我們可以調用%debug:這就可以開啟IPython的調試模式,它可以監視異常發生處的變量。這一操作比在代碼中添加print函數再執行代碼的調試效率要高得多。
如果你使用了這一操作,你可能還會用到up命令(在調試窗中輸入d)和down命令(在調試窗中輸入d),這兩個命令改變監視堆棧上和下的方向(堆棧中往上表示當前函數已經調用的函數;往下與之相反)。
繪圖
用IPython console繪圖
假設我們使用的IPython console的版本大於等於1.0.0,我們就可以決定matplotlib/pylab產生的圖表用哪種方式顯示:
1.在命令行中顯示,例如顯示在IPython console中;
2.顯示在一個新窗口中。
選項1可以很方便的保存交互會話的內容(在有用的快捷方式一節中介紹了如何使用快捷方式將IPython console的內容保存為html文件)。
選項2則允許一些交互式的操作,比如放大圖表,操作圖表,通過窗口包含的菜單將圖表保存成各種格式。
在IPython console中顯示圖表的命令是:
In [3]: %matplotlib inline
- 1
Spyder的參數配置可以個性化設置默認行為(通過Preferences > IPython Console > Graphics > Activate Support轉換到命令行中繪圖)。
如下兩行命令可以快速生成一個圖表,你可以試一下:
In [5]: import pylab In [6]: pylab.plot(range(10), 'o')
- 1
- 2
用Python console繪圖
如果我們使用Python console,所有的圖表都會顯示在新窗口中(沒有辦法將它顯示在Python console的命令行中)。
如下是一個簡單的例子,你可以測試一下:
>>> import pylab >>> pylab.plot(range(10), 'o')
- 1
- 2
如果你在專用的控制台中執行代碼,你需要在代碼中使用matplotlib或者pylab的show()命令使圖表顯示出來,如:pylab.show()。
注意,show()命令將綁定到已經出現的新窗口上,也就是說你需要關掉那個窗口之后Spyder才會接受其他的命令或響應交互。如果你沒看到新的窗口,檢查一下它是否顯示在Spyder窗口的后面,或者它被隱藏了。
歷史說明
這一教程是基於Hans Fangohr的說明編寫的,這在南安普頓大學的下一代計算建模博士培訓中心用於教授Python的計算模型給本科生工程師、研究生和博士生。