Python是一門簡單易學(xué),功能強(qiáng)大的編程語言。它具有高效的高層次數(shù)據(jù)結(jié)構(gòu),簡單但有效的方式支持面向?qū)ο缶幊蹋Z法優(yōu)雅,動態(tài)類型,解釋執(zhí)行。使之成為多數(shù)平臺上很多領(lǐng)域的腳本和快速應(yīng)用開發(fā)的理想語言。
Python解釋器及其豐富的標(biāo)準(zhǔn)庫的源碼或者二進(jìn)制版本可以從http://www.python.org/免費(fèi)獲取和轉(zhuǎn)發(fā)。該還包含很多免費(fèi)的第三方Python模塊、程序、工具的發(fā)布鏈接及附加文檔。
Python的解釋器很容易用C或C++(或其他c可以調(diào)用的語言)擴(kuò)展新功能和數(shù)據(jù)類型。 Python也適用于作為定制應(yīng)用的擴(kuò)展語言。
本教程向讀者通俗地介紹Python語言和系統(tǒng)的基本概念和特點(diǎn)。配合Python解釋器邊學(xué)邊練最佳,所有例子已經(jīng)自包含在教程中,也可離線閱讀。
標(biāo)準(zhǔn)對象和模塊參見The Python Standard Library。The Python Language Reference提供了Python更正式的說明。要用C或C++編寫擴(kuò)展參見Extending and Embedding the Python InterPReter和Python/C API Reference Manual。
本教程不會面面俱到。它介紹了許多Python的最引人注目的特性,會讓你了解python風(fēng)格。看完之后可閱讀和編寫Python模塊。
所有例子基于linux演示,不考慮Windows。
如果你做很多電腦上工作,最終你發(fā)現(xiàn),有些任務(wù)你想實(shí)現(xiàn)自動化。例如你在大量的文本文件上執(zhí)行搜索和替換,或通過復(fù)雜的方式重命名和重整一批照片文件。也許你想編寫小型的自定義數(shù)據(jù)庫,或者專門的圖形用戶界面應(yīng)用程序,或簡單的游戲。
如果你是個(gè)專業(yè)的軟件開發(fā),你可能處理幾個(gè)C/C++/java庫,編寫/編譯/測試/重編譯周期太慢。也許你正在為庫編寫測試套件,發(fā)現(xiàn)書寫測試代碼是個(gè)體力活。或者應(yīng)用程序需要一門擴(kuò)展語言,但是不想設(shè)計(jì)和實(shí)施新的語言。
Python就是你需要的語言。
你 可以為這些任務(wù)寫Unix shell腳本或Windows批處理文件,但shell腳本更適合移動文件和更改文本數(shù)據(jù),不擅長圖形用戶界面的應(yīng)用程序或游戲。你可以寫一個(gè) C/C++/Java程序,但需要消耗大量開發(fā)時(shí)間。 Python易于使用,可用于Windows,Mac OS X和Unix操作系統(tǒng),并幫助你更快速地完成工作。
Python雖然使用簡單,但是真正的編程語言。跟shell腳本或批處理文件比,它提 供更多的結(jié)構(gòu)并支持大型程序。Python比C提供了更多的錯誤檢查。它是更高級別的語言,內(nèi)置了的高級數(shù)據(jù)類型,如靈活的數(shù)組和字典。基于這些通用數(shù)據(jù) 類型, Python相對Awk甚至是Perl可以處理很多領(lǐng)域的難題,很多東東在python中會比其他語言處理起來更容易。
Python允許你分割程序?yàn)槟K,以便在其他Python程序重復(fù)使用。它包含了豐富的標(biāo)準(zhǔn)模塊,你可以調(diào)用或?qū)W習(xí)。一些模塊提供如文件I/O,系統(tǒng)調(diào)用,socket,甚至像Tk圖形用戶界面接口。
Python是解釋語言,程序開發(fā)時(shí)不需要編譯和鏈接而節(jié)省可觀的時(shí)間。解釋器可交互使用,方便試驗(yàn)的語言特性,寫信手而用的程序,還可在自下而上的程序開發(fā)時(shí)測試功能,同時(shí)是方便的桌面計(jì)算器。
Python編寫的應(yīng)用程序緊湊,可讀性好。 Python程序通常同樣的C ,C++或Java程序要短得多,原因如下:
高級數(shù)據(jù)類型允許你在單條語句中表示復(fù)雜的操作;
語句的組織依賴于縮進(jìn)而不是開始和結(jié)束的括號;
變量或參數(shù)聲明不是必須的。
Python是可擴(kuò)展的:懂C的話很容易添加新的內(nèi)置函數(shù)或模塊到解釋器,可以最快速度執(zhí)行關(guān)鍵操作或鏈接Python程序到二進(jìn)制庫(如供應(yīng)商特定的圖形庫)。等你熟悉之后,可以鏈接Python解釋器到C應(yīng)用程序,并用它作為擴(kuò)展或命令語言。
Python的名字來源于英國廣播公司(BBC)節(jié)目"Monty Python’s Flying Circus",與爬行動物無關(guān)。
現(xiàn)在大家已經(jīng)對Python產(chǎn)生了興趣,想了解更多。學(xué)習(xí)一門語言的最好方式就是使用它,讓我們首先學(xué)習(xí)Python解釋器。
教程的其他部分通過實(shí)例介紹了Python語言和系統(tǒng)的各種特性。先是簡單表達(dá)式,語句和數(shù)據(jù)類型,然后函數(shù)和模塊,最后是高級概念比如異常和用戶定義的類。
解釋器的操作有些像Unix Shell:當(dāng)標(biāo)準(zhǔn)輸入連接到tty設(shè)備時(shí),它讀取并以交互方式執(zhí)行命令;當(dāng)文件名參數(shù)或以文件作為標(biāo)準(zhǔn)輸入設(shè)備時(shí),它讀取并執(zhí)行文件中腳本。
Python的解釋器在linux上通常安裝在/usr/bin/python,/usr/local/bin/python,/usr/local/bin/python等地方。Windows一般位于C:/Python27,且一般需要設(shè)置PATH環(huán)境變量。
#pythonPython 2.7.5 (default, Jun 17 2014, 18:11:42) [GCC 4.8.2 20140120 (Red Hat 4.8.2-16)] on linux2Type "help", "copyright", "credits" or "license" for more information.
退出解釋器:Linux上Control-D,Windows上Control-Z,統(tǒng)一的方式:quit()。
解釋器的行編輯功能并不復(fù)雜。在Unix上,解釋器可能已啟用了GNU readline庫,它增加了更多的交互編輯和歷史記錄功能。輸入Control-P,如果發(fā)出嗶嗶聲表示支持readline;見附錄交互式輸入編輯和歷史替換https://docs.python.org/2/tutorial/interactive.html。
解釋器的操作有些像Unix Shell:當(dāng)標(biāo)準(zhǔn)輸入連接到tty設(shè)備時(shí),它讀取并以交互方式執(zhí)行命令;當(dāng)文件名參數(shù)或以文件作為標(biāo)準(zhǔn)輸入設(shè)備時(shí),它讀取并執(zhí)行文件中腳本。 啟動解釋器的第二個(gè)方法是python -c command [arg] ...,執(zhí)行command中的語句,等同于Shell的-c選項(xiàng)。因?yàn)镻ython語句通常會包括空格或其他shell的特殊字符是特殊的外殼,建議使 把command放在單引號中。注意因?yàn)榭s進(jìn)原因,開始的引號后面不能有空格。
$ python -c "print 'Hello'"Hello$ python -c 'print "Hello"'Hello
一些Python模塊也作為腳本使用:python -m module [arg] ...。
使用腳本文件時(shí),-i參數(shù)可以進(jìn)入交互模式。
比如有test.py文件如下:
print("Hello")print("World!")
執(zhí)行:
$ python -i test.pyHelloWorld!>>>腳本名和附加參數(shù)轉(zhuǎn)換成字符串列表傳遞給sys模塊中的argv變量。導(dǎo)入sys模塊訪問這個(gè)列表。列表的長度至少為1,在無腳本無參數(shù)時(shí),sys.argv[0]是空字符串。當(dāng)腳本名為"-"(即標(biāo)準(zhǔn)輸入),sys.argv[0]為"-"。使用-c參數(shù)時(shí),sys.argv中[0]設(shè)置為'-c'。使用-m參數(shù)sys.argv中[0]設(shè)置為模塊的全名。-c或-m之后的選項(xiàng)留在sys.argv中待命令或模塊來處理。
可以用sys.argv來處理參數(shù):
#!/usr/bin/env python# encoding: utf-8 import sys print "script name is", sys.argv[0]if len(sys.argv) > 1: print "there are", len(sys.argv)-1, "arguments:" for arg in sys.argv[1:]: print argelse: print "there are no arguments!"
$ ./test.py 1 2 3script name is ./test.pythere are 3 arguments:123
注意:通常python標(biāo)準(zhǔn)模塊argparse處理參數(shù)會更合適。
當(dāng)tty讀取命令時(shí)解釋器為交互模式。主命令提示符為(>>>),從命令提示符(...)用于續(xù)行。
$ pythonPython 2.7.6 (default, Jun 22 2015, 17:58:13) [GCC 4.8.2] on linux2Type "help", "copyright", "credits" or "license" for more information.>>> the_world_is_flat = 1>>> if the_world_is_flat:... print "Be careful not to fall off!"
當(dāng)錯誤發(fā)生時(shí),解釋器打印錯誤信息和棧跟蹤。在交互模式下,它返回主提示符;在文件輸入時(shí),打印棧跟蹤器后以非零退出狀態(tài)退出。有些錯誤致命的,無條件以非零退出的退出,比如內(nèi)部不一致和內(nèi)存耗盡。所有的錯誤信息都寫入標(biāo)準(zhǔn)錯誤流;正常輸出寫入標(biāo)準(zhǔn)輸出。
輸入中斷符(通常是Control-C或DEL)可以取消輸入,命令執(zhí)行時(shí)輸入中斷引發(fā)一個(gè)KeyboardInterrupt異常。
Linux系統(tǒng)中,Python腳本可直接執(zhí)行,就像shell腳本,在文件首行添加如下:
#! /usr/bin/env python
并添加可執(zhí)行權(quán)限:
chmod +x myscript.py
Windows系統(tǒng)中Python的安裝程序會自動關(guān)聯(lián)*.py到python.exe,雙擊即可運(yùn)行。*.pyw則不會出現(xiàn)windows控制臺。
使用的編碼ASCII(默認(rèn))以外的字符Python的源文件,可以在行#!之后定義源文件編碼:
# -*- coding: encoding -*-
根據(jù)這個(gè)聲明,源文件中的所有字符將用該編碼的編碼,并可能在用選定的編碼書寫Unicode字符串。編碼列表可以在Python庫參考手冊的codecshttps://docs.python.org/2/library/codecs.html部分找到。實(shí)例:
一般推薦使用utf-8的格式,在網(wǎng)絡(luò)上比較通用,可以這樣設(shè)置:
# coding=utf-8
特殊的中文處理可以使用gbk。通常為了正確顯示所有的字符,編輯器必須支持utf-8等格式,并有相應(yīng)的字體。
交互式使用Python的時(shí)候,常常需要在解釋器啟動時(shí)執(zhí)行一些標(biāo)準(zhǔn)命令。可設(shè)置環(huán)境變量PYTHONSTARTUP表示啟動命令文件,類似Unix shell的.profile文件。
文件只對交互會話有效,當(dāng) Python 從腳本中讀取命令或以終端/dev/tty做為外部命令源(行為和交互式會話類似)。它與解釋器執(zhí)行的命令在同一命名空間,這樣它定義或?qū)氲膶ο罂梢栽?解釋器中使用。也可以在這個(gè)文件中改變提示符sys.ps1和sys.ps2。
加載其他文件的方式:
if os.path.isfile('.pythonrc.py'): execfile('.pythonrc.py')
在腳本中使用啟動文件如下:
import osfilename = os.environ.get('PYTHONSTARTUP')if filename and os.path.isfile(filename): execfile(filename)
Python有兩個(gè)hook: sitecustomize 和 usercustomize。使用它們首先需要知道site-packages目錄,方法如下:
>>> import site >>> site.getusersitepackages() '/root/.local/lib/python2.7/site-packages'
現(xiàn)在你可以在site-packages的目錄下創(chuàng)建文件usercustomize.py,放入你想添加的任何內(nèi)容。 該文件會影響 python 的每次調(diào)用,除非啟動的時(shí)候加入-s選項(xiàng)禁止自動導(dǎo)入。
類似的有sitecustomize,但是一般由管理員在全局site-packages創(chuàng)建,在usercustomize之前導(dǎo)入,更多資料參見site模塊https://docs.python.org/2/library/site.html。
下面的例子中,輸入和輸出分別由>>>和...開始。
Python中的注釋以#字符起始,到行尾。實(shí)例如下:
Python 2.7.6 (default, Jun 22 2015, 17:58:13) [GCC 4.8.2] on linux2Type "help", "copyright", "credits" or "license" for more information.>>> the_world_is_flat = 1>>> if the_world_is_flat:... print "Be careful not to fall off!"... Be careful not to fall off!
解釋器像簡單的計(jì)算器:可以輸入表達(dá)式,它會返回值。表達(dá)式語法很簡單:運(yùn)算符 + , - , * 和 / 與其它語言一樣(例如Pascal或C);括號用于分組。例如:
>>> 2 + 24>>> 50 - 5*620>>> (50 - 5.0*6) / 45.0>>> 8 / 5.01.6
"/" 的返回類型取決于操作數(shù)。如果兩個(gè)操作數(shù)都是int類型,執(zhí)行地板除(參見https://docs.python.org/2 /glossary.html#term-floor-division)和返回int。如果操作數(shù)有浮點(diǎn)數(shù),執(zhí)行經(jīng)典除法和并返回浮點(diǎn)數(shù),浮點(diǎn)數(shù)的地板 除可以使用//。取余使用%:
>>> 17 / 3 # int / int -> int5>>> 17 / 3.0 # int / float -> float5.666666666666667>>> 17 // 3.0 # explicit floor division discards the fractional part5.0>>> 17 % 3 # the % Operator returns the remainder of the division2>>> 5 * 3 + 2 # result * divisor + remainder17
"**"表示乘方:
>>> 5 ** 2 # 5 squared25>>> 2 ** 7 # 2 to the power of 7128
等號( '=' )用于給變量賦值:
>>> width = 20>>> height = 5*9>>> width * height900同一值可以同時(shí)賦給幾個(gè)變量:
>>> x = y = z = 0 # Zero x, y and z>>> x0>>> y0>>> z0
變量在使用前必須"定義"(賦值),否則會出錯:
>>> nTraceback (most recent call last): File "<stdin>", line 1, in <module>NameError: name 'n' is not defined
支持浮點(diǎn)數(shù),混合計(jì)算時(shí)會自動整型轉(zhuǎn)為浮點(diǎn)數(shù):
>>> 3 * 3.75 / 1.57.5>>> 7.0 / 23.5
交互模式中,最近表達(dá)式的值賦給變量 _ 。更方便連續(xù)計(jì)算把Python當(dāng)作桌面計(jì)算器,例如:
>>> tax = 12.5 / 100>>> price = 100.50>>> price * tax12.5625>>> price + _113.0625>>> round(_, 2)113.06
此變量對于用戶是只讀的。
除了int和float,還有fractions(https://docs.python.org/2/library/fractions.html#fractions.Fraction)和decimal(https://docs.python.org/2/library/decimal.html#decimal.Decimal)。
下面的復(fù)數(shù)部分很少使用,通常可以不閱讀。
支持復(fù)數(shù),虛數(shù)帶有后綴j或J,有非零實(shí)部的復(fù)數(shù)寫為(real+imagj),或者用complex(real, imag)函數(shù)創(chuàng)建。
>>> 1j * 1J(-1+0j)>>> 1j * complex(0,1)(-1+0j)>>> 3+1j*3(3+3j)>>> (3+1j)*3(9+3j)>>> (1+2j)/(1+1j)(1.5+0.5j)
復(fù)數(shù)的實(shí)部和虛部總是記為兩個(gè)浮點(diǎn)數(shù)。要從復(fù)數(shù)z中提取實(shí)部和虛部,使用z.real和 z.imag。
>>> a=1.5+0.5j>>> a.real1.5>>> a.imag0.5
浮點(diǎn)數(shù)和整數(shù)轉(zhuǎn)換函數(shù)(float(), int()和long())不適用于復(fù)數(shù)。沒有方法把復(fù)數(shù)轉(zhuǎn)成實(shí)數(shù)。函數(shù)abs(z)用于取模(為浮點(diǎn)數(shù))或z.real取實(shí)部:
>>> a=3.0+4.0j>>> float(a)Traceback (most recent call last): File "<stdin>", line 1, in <module>TypeError: can't convert complex to float>>> a.real3.0>>> a.imag4.0>>> abs(a) # sqrt(a.real**2 + a.imag**2)5.0
字符串可以包含在單引號或雙引號中。
>>> 'spam eggs''spam eggs'>>> 'doesn/'t'"doesn't">>> "doesn't""doesn't">>> '"Yes," he said.''"Yes," he said.'>>> "/"Yes,/" he said."'"Yes," he said.'>>> '"Isn/'t," she said.''"Isn/'t," she said.'
解釋器按照字符串被輸入的方式顯示字符串,通常包含在單引號中,如果內(nèi)容包含包含單引號,則包含在雙引號中。
print會以更可視的格式顯示:
>>> '"Isn/'t," she said.''"Isn/'t," she said.'>>> print '"Isn/'t," she said.'"Isn't," she said.>>> s = 'First line./nSecond line.' # /n means newline>>> s'First line./nSecond line.'>>> print s # with print, /n produces a new lineFirst line.Second line.
字符串前面添加'r'表示原始字符串,里面的反斜杠不會轉(zhuǎn)義:
>>> print 'C:/some/name' # here /n means newline!C:/someame>>> print r'C:/some/name' # note the r before the quoteC:/some/name
跨行的字符串多使用三引號,即三個(gè)單引號或者三個(gè)雙引號:
>>> print """/... Usage: thingy [OPTIONS]... -h Display this usage message... -H hostname Hostname to connect to... """Usage: thingy [OPTIONS] -h Display this usage message -H hostname Hostname to connect to >>> print """... Usage: thingy [OPTIONS]... -h Display this usage message... -H hostname Hostname to connect to... """ Usage: thingy [OPTIONS] -h Display this usage message -H hostname Hostname to connect to
注意第一個(gè)三引號后面有反斜杠,就不會輸出第一個(gè)換行符。末尾的反斜杠表示續(xù)行。
字符串可用+操作符連接,用*重復(fù):
>>> 3 * 'un' + 'ium''unununium'
相鄰字符串文本會自動連接,它只用于字符串文本,不能用于字符串表達(dá)式和變量(需要使用加號)等:
>>> 'Py' 'thon''Python'>>> prefix 'thon File "<stdin>", line 1 prefix 'thon ^SyntaxError: EOL while scanning string literal>>> ('un' * 3) 'ium' File "<stdin>", line 1 ('un' * 3) 'ium' ^SyntaxError: invalid syntax>>> prefix + 'thon''Python'# 在拆分長字符串時(shí)很有用。>>> text = ('Put several strings within parentheses '... 'to have them joined together.')>>> text'Put several strings within parentheses to have them joined together.'
字符串下標(biāo)又稱索引和C類似 ,第一個(gè)字符索引為 0 。沒有獨(dú)立的字符類型,字符就是長度為 1 的字符串,也可以使用負(fù)數(shù),-1表示倒數(shù)第一個(gè),-2表示倒數(shù)第二個(gè),以此類推。不存在的下標(biāo)會報(bào)IndexError。
>>> Word = 'Python'>>> word[0] # character in position 0'P'>>> word[5] # character in position 5'n'>>> word[-1] # last character'n'>>> word[-2] # second-last character'o'>>> word[-6]'P'>>> word[-16]Traceback (most recent call last): File "<stdin>", line 1, in <module>IndexError: string index out of range>>> word[16]Traceback (most recent call last): File "<stdin>", line 1, in <module>IndexError: string index out of range
字符串支持切片:由兩個(gè)索引,中間是冒號。第一個(gè)索引表示起點(diǎn),包含該元素,默認(rèn)為0;第2個(gè)索引表示終點(diǎn),不包含該元素,默認(rèn)為字符串末尾。s[:i] + s[i:]等同于s。
>>> word[0:2] # characters from position 0 (included) to 2 (excluded)'Py'>>> word[2:5] # characters from position 2 (included) to 5 (excluded)'tho'>>> word[:2] + word[2:]'Python'>>> word[:4] + word[4:]'Python'>>> word[:2] # character from the beginning to position 2 (excluded)'Py'>>> word[4:] # characters from position 4 (included) to the end'on'>>> word[-2:] # characters from the second-last (included) to the end'on'
記住切片的工作方式:切片索引是在字符之間。左邊第一個(gè)字符的索引為0,右界索引為字符串長度n 。例如:
+---+---+---+---+---+ | H | e | l | p | A | +---+---+---+---+---+ 0 1 2 3 4 5-5 -4 -3 -2 -1
第一行數(shù)字給出字符串正索引點(diǎn)值0...5 。第二行給出相應(yīng)的負(fù)索引。切片是從 i 到 j 兩個(gè)數(shù)值標(biāo)示的邊界之間的所有字符。
對于非負(fù)索引,如果兩個(gè)索引都在邊界內(nèi),切片長度就是兩個(gè)索引之差。例如, word[1:3] 是 2 。
切片時(shí),下標(biāo)溢出不會報(bào)錯。
>>> word[4:42]'on'>>> word[43:42]''
Python的字符串是不可變。向字符串文本的某一個(gè)索引賦值會引發(fā)錯誤:
>>> word[0] = 'J'Traceback (most recent call last): File "<stdin>", line 1, in <module>TypeError: 'str' object does not support item assignment
通過聯(lián)合(加號)可以簡單高效的創(chuàng)建字符串。(注,jython中這種操作并不高效)。
>>> 'J' + word[1:]'Jython'>>> word[:2] + 'py''Pypy'
內(nèi)置函數(shù)len()返回字符串長度:
>>> s = 'supercalifragilisticexpialidocious'>>> len(s)34
參考資料:
Sequence Types — str, unicode, list, tuple, bytearray, buffer, xrange https://docs.python.org/2/tutorial/introduction.html
String Methods: https://docs.python.org/2/library/stdtypes.html
String Formatting:https://docs.python.org/2/library/string.html
String Formatting Operations: https://docs.python.org/2/library/stdtypes.html
Python2.0增加了新的用來存儲文本數(shù)據(jù)的類型:Unicode對象。它可以用于存儲和操作Uounicode 數(shù)據(jù)(參見 http://www.unicode.org/),與現(xiàn)有的字符串兼容性良好,必要時(shí)能自動轉(zhuǎn)換。
Unicode支持所有字符的表示,之前的ASCII只支持256個(gè)字符。更多Unicode相關(guān)的資料,參見:http://zh.wikipedia.org/wiki/Unicode。
創(chuàng)建Unicode字符串:
>>> u'Hello World !'u'Hello World !'
引號前的'u'表示Unicode 字符串,轉(zhuǎn)義的方式可以創(chuàng)建其他字符:
>>> u'Hello/u0020World !'u'Hello World !'
轉(zhuǎn)義序列/u0020表示插入編碼為0x0020(空格)的Unicode 字符。
其他字符也會直接解釋為對應(yīng)的編碼值。 許多西方國家使用的標(biāo)準(zhǔn)Latin-1編碼的字符串和編碼小于256的Unicode字符和在Unicode編碼中的一樣。
使用ur可以取消轉(zhuǎn)義,r表示原始格式(raw)。
>>> ur'Hello/u0020World !'u'Hello World !'>>> ur'Hello//u0020World !'u'Hello////u0020World !'
如果你需要大量輸入反斜杠(比如正則表達(dá)式),原始模式非常有用。
除了標(biāo)準(zhǔn)編碼,Python還支持其他編碼。
內(nèi)置函數(shù)unicode()可以訪問所有注冊的Unicode編碼(COders和DECoders),并支持Latin-1 、ASCII、UTF-8和UTF-16 之類的編碼可以互相轉(zhuǎn)換,后兩個(gè)是變長編碼。通常默認(rèn)編碼為 ASCII,此編碼接受0到127 這個(gè)范圍的編碼,否則報(bào)錯。Unicode字符串打印或?qū)懭氲轿募蛘呤褂胹tr()轉(zhuǎn)換時(shí),使用默認(rèn)編碼進(jìn)行轉(zhuǎn)換操作。
encode()方法可以把Unicode字符串轉(zhuǎn)換為特定編碼的8bit字符串,參數(shù)為小寫的編碼名作為參數(shù)。
反之可以使用unicode()把其他編碼轉(zhuǎn)換為unicode。
>>> u"abc"u'abc'>>> str(u"abc")'abc'>>> u"äöü"u'/xe4/xf6/xfc'>>> str(u"äöü")Traceback (most recent call last): File "<stdin>", line 1, in <module>UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-2: ordinal not in range(128)>>> u"äöü".encode('utf-8')'/xc3/xa4/xc3/xb6/xc3/xbc'>>> unicode('/xc3/xa4/xc3/xb6/xc3/xbc', 'utf-8')u'/xe4/xf6/xfc'
Python有一些復(fù)合數(shù)據(jù)類型,用于組合值。最常用的是 list(列表)),為中括號之間的逗號分隔的值。列表的元素可以是多種類型,但是通常是同一類型。
>>> squares = [1, 4, 9, 16, 25]>>> squares[1, 4, 9, 16, 25]
像字符串和其他序列類型,列表可支持切片和索引:
>>> squares[0] # indexing returns the item1>>> squares[-1]25>>> squares[-3:] # slicing returns a new list[9, 16, 25]
切片返回新的列表,下面操作返回列表a的淺拷貝:
>>> squares[:][1, 4, 9, 16, 25]列表還支持連接:
>>> squares + [36, 49, 64, 81, 100][1, 4, 9, 16, 25, 36, 49, 64, 81, 100]字符串是不可改變的,列表是可變的。
>>> cubes = [1, 8, 27, 65, 125] # something's wrong here>>> 4 ** 3 # the cube of 4 is 64, not 65!64>>> cubes[3] = 64 # replace the wrong value>>> cubes[1, 8, 27, 64, 125]
append()方法可以添加元素到尾部:
>>> cubes.append(216) # add the cube of 6>>> cubes.append(7 ** 3) # and the cube of 7>>> cubes[1, 8, 27, 64, 125, 216, 343]
也可以對切片賦值,此操作甚至可以改變列表的尺寸,或清空它:
>>> letters = ['a', 'b', 'c', 'd', 'e', 'f', 'g']>>> letters['a', 'b', 'c', 'd', 'e', 'f', 'g']>>> # replace some values>>> letters[2:5] = ['C', 'D', 'E']>>> letters['a', 'b', 'C', 'D', 'E', 'f', 'g']>>> # now remove them>>> letters[2:5] = []>>> letters['a', 'b', 'f', 'g']>>> # clear the list by replacing all the elements with an empty list>>> letters[:] = []>>> letters[]
內(nèi)置函數(shù) len() 同樣適用于列表:
>>> letters = ['a', 'b', 'c', 'd']>>> len(letters)4
支持嵌套列表(包含其它列表的列表),例如:
>>> a = ['a', 'b', 'c']>>> n = [1, 2, 3]>>> x = [a, n]>>> x[['a', 'b', 'c'], [1, 2, 3]]>>> x[0]['a', 'b', 'c']>>> x[0][1]'b'
Python可以完成比二加二更復(fù)雜的任務(wù)。下面是菲波那契序列:
>>> # Fibonacci series:... # the sum of two elements defines the next... a, b = 0, 1>>> while b < 10:... print b... a, b = b, a+b... 112358
本例的新特性。
第一行和最后一行有多賦值:第一行變量a和b同時(shí)獲得了新的值0和1。最后一行右邊首先完成計(jì)算,右邊的表達(dá)式從左到右計(jì)算。
條件(b < 10)為true時(shí)while循環(huán)執(zhí)行。這里Python類似C ,任何非零整數(shù)都為true;0為 false。判斷條件也可以是字符串或列表等序列;所有長度不為零的為true ,空序列為false。示例中的測試是一個(gè)簡單的比較。標(biāo)準(zhǔn)比較操作符與C相同: <(小于), >(大于), ==(等于),<=(小于等于),>=(大于等于)和!=(不等于)。
循環(huán)體需要縮進(jìn):縮進(jìn)是Python組織語句的方法。在命令行下,縮進(jìn)行需要插入空格或者tab。建議使用文本編輯 或者IDE,一般都提供自動縮進(jìn)。命令行輸入復(fù)合語句時(shí),必須用空行來標(biāo)識結(jié)束(因?yàn)榻忉屍鳑]辦法猜識別最后一行),注意同一級的語句需要縮進(jìn)同樣數(shù)量的 空白。建議使用空格而不是tab縮進(jìn)。
print語句輸出表達(dá)式的值。字符串打印時(shí)沒有引號,每兩個(gè)項(xiàng)目之間有空格。
逗號結(jié)尾就可以避免輸出換行:
>>> a, b = 0, 1>>> while b < 1000:... print b,... a, b = b, a+b... 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987
Pexpect 是一個(gè)用來啟動交互式命令行子程序并對其進(jìn)行自動控制的 Python 模塊。 Pexpect 可以用來和像 ssh、ftp、passwd、telnet 等命令行程序進(jìn)行自動交互。可廣泛用于自動化運(yùn)維和測試,實(shí)現(xiàn)同時(shí)控制多臺設(shè)備和自動化。Linux中的知名裝包軟件就使用了Pexpect。 Pexpect在IBM,alibaba,google等公司有廣泛使用,在https://pypi.python.org/pypi/pexpect 的日下載量一萬左右。
純python實(shí)現(xiàn),依賴pty模塊(不支持Windows)。
最新英文版文檔參見:http://pexpect.readthedocs.org/en/latest/
安裝:
版本要求:Python 2.6、3.2 或以上
ssh登錄是常用的操作,過程如下:
$ ssh root@10.6.0.232root@10.6.0.232's password: Last login: Thu Sep 17 08:58:49 2015 from 10.6.3.223[root@AutoTest ~]#
下面我們用pexpect來自動實(shí)現(xiàn)這個(gè)過程:
#!/usr/bin/env python# -*- coding: utf-8 -*- # 導(dǎo)入pexpect庫import pexpect# 發(fā)起ssh連接到10.6.0.232的子進(jìn)程,使用root用戶child = pexpect.spawn('ssh root@10.6.0.232')child.expect('password:') # 等待password:字符出現(xiàn)print child.before + child.after # 輸出password:前后的字符child.sendline('password') # 發(fā)送密碼child.expect(']#') # 等待]#字符出現(xiàn)print child.before + child.after child.interact() # 把ssh的連接交給用戶控制。
上面最后一句在非交互式的情況下要關(guān)閉連接,用child.close()替換即可。
上 述操作除了interact外,都可以用python的ssh模塊:paramiko代替。不過對于一些同時(shí)支持telenet、ftp、ssh等協(xié)議命 令行的通信設(shè)備,可以用pexpect通殺。telenet、ftp、ssh等從協(xié)議的層次聯(lián)系,pexpect會更接近用戶使用,更加適合自動化測試。
兩個(gè)重要方法: expect()和send() (以及sendline() )。expect可以接受正則表達(dá)式作為參數(shù)。
before包含預(yù)期字符串之前的信息, after包含匹配模式及其以后的內(nèi)容。
EOF(End Of File)與TIMEOUT可以在expect方法中使用,它們不是正則表達(dá)式,而是常量。
源于異常,而不是BaseException例外。從BaseException直接繼承的例外情況趕上他們幾乎總是錯誤的做法保留。
如果子進(jìn)程已經(jīng)退出,讀取子進(jìn)程的輸出會引發(fā)EOF異常。此時(shí)子進(jìn)程的輸出全部在before中。
expect()接受的參數(shù)是正則表達(dá)式或正則表達(dá)式列表,可匹配多個(gè)可選的響應(yīng)。比如ssh登錄的各種情況處理:
class Ssh(object): client = None @classmethod def connect(cls, ip, username="root", password="123456", prompt=']#', silent=False): # Ssh to remote server ssh_newkey = 'Are you sure you want to continue connecting' child = pexpect.spawn('ssh ' + username + '@' + ip, maxread=5000) i = 1 # Enter password while i != 0: i = child.expect([prompt, 'assword:*', ssh_newkey, pexpect.TIMEOUT, 'key.*? failed']) if not silent: print child.before + child.after, if i == 0: # find prompt pass elif i == 1: # Enter password child.send(password + "/r") if i == 2: # SSH does not have the public key. Just accept it. child.sendline('yes/r') if i == 3: # Timeout raise Exception('ERROR TIMEOUT! SSH could not login. ') if i == 4: # new key print child.before, child.after, os.remove(os.path.expanduser('~') + '/.ssh/known_hosts') Ssh.client = child @classmethod def command(cls, cmd, prompt=']#', silent=False): Ssh.client.buffer = '' Ssh.client.send(cmd + "/r") # Ssh.client.setwinsize(400,400) Ssh.client.expect(prompt) if not silent: print Ssh.client.before + Ssh.client.after, return Ssh.client.before, Ssh.client.after @classmethod def close(cls,): Ssh.client.close()
expect()的超時(shí)默認(rèn)為30秒,超時(shí)時(shí)生成TIMEOUT異常。可以修改:
# Wait no more than 2 minutes (120 seconds) for password prompt.child.expect('password:', timeout=120)
Pexpect匹配的正則表達(dá)式與標(biāo)準(zhǔn)的有些差異,默認(rèn)是非貪婪匹配。Pexpect一次讀取一個(gè)字符讀,這樣行尾標(biāo)識$失去了意義。行尾用"/r/n"(CR/LF)表示。Pexpect中的"/n"實(shí)際對應(yīng)"/r/n"。匹配行尾的操作如下:
child.expect('/r/n')
盡量用:
child.expect ('.+')
而不是:
child.expect ('.*')
pexpect.screen和pexpect.ANSI在版本4已經(jīng)不推薦使用,建議用pyte替代。
def __init__(self, command, args=[], timeout=30, maxread=2000, searchwindowsize=None, logfile=None, cwd=None, env=None, ignore_sighup=True):
調(diào)用示例:
child = pexpect.spawn('/usr/bin/ftp')child = pexpect.spawn('/usr/bin/ssh user@example.com')child = pexpect.spawn('ls -latr /tmp')child = pexpect.spawn('/usr/bin/ftp', [])child = pexpect.spawn('/usr/bin/ssh', ['user@example.com'])child = pexpect.spawn('ls', ['-latr', '/tmp'])
pexpect不能解釋shell元字符,比如 (>, |, or *),需要啟動shell來解決該問題:
child = pexpect.spawn('/bin/bash -c "ls -l | grep LOG > logs.txt"')child.expect(pexpect.EOF)
日志輸出:
child = pexpect.spawn('some_command')fout = open('mylog.txt','wb')child.logfile = fout
輸出到stdout
# In Python 2:child = pexpect.spawn('some_command')child.logfile = sys.stdout# In Python 3, spawnu should be used to give str to stdout:child = pexpect.spawnu('some_command')child.logfile = sys.stdout
== 未完待續(xù)
python 2.7 英文官方教程:https://docs.python.org/2/tutorial/
paramiko: https://pypi.python.org/pypi/paramiko
pexpect: https://pypi.python.org/pypi/pexpect
pexpect英文文檔:http://pexpect.readthedocs.org/en/latest/
新聞熱點(diǎn)
疑難解答
圖片精選