Python 面向?qū)ο驪ython從設(shè)計(jì)之初就已經(jīng)是一門面向?qū)ο蟮恼Z言佳遣,正因?yàn)槿绱酥视赑ython中創(chuàng)建一個(gè)類和對象是很容易的绑嘹。本章節(jié)我們將詳細(xì)介紹Python的面向?qū)ο缶幊坦H绻阋郧皼]有接觸過面向?qū)ο蟮木幊陶Z言年碘,那你可能需要先了解一些面向?qū)ο笳Z言的一些基本特征,在頭腦里頭形成一個(gè)基本的面向?qū)ο蟮母拍钫辜Γ@樣有助于你更容易的學(xué)習(xí)Python的面向?qū)ο缶幊逃煨啤=酉聛砦覀兿葋砗唵蔚牧私庀旅嫦驅(qū)ο蟮囊恍┗咎卣鳌C嫦驅(qū)ο蠹夹g(shù)簡介類(Class): 用來描述具有相同的屬性和方法的對象的集合莹弊。它定義了該集合中每個(gè)對象所共有的屬性和方法傲诵。對象是類的實(shí)例。類變量:類變量在整個(gè)實(shí)例化的對象中是公用的箱硕。類變量定義在類中且在函數(shù)體之外拴竹。類變量通常不作為實(shí)例變量使用。數(shù)據(jù)成員:類變量或者實(shí)例變量用于處理類及其實(shí)例對象的相關(guān)的數(shù)據(jù)剧罩。方法重寫:如果從父類繼承的方法不能滿足子類的需求栓拜,可以對其進(jìn)行改寫,這個(gè)過程叫方法的覆蓋(override)惠昔,也稱為方法的重寫幕与。實(shí)例變量:定義在方法中的變量,只作用于當(dāng)前實(shí)例的類镇防。繼承:即一個(gè)派生類(derived class)繼承基類(base class)的字段和方法啦鸣。繼承也允許把一個(gè)派生類的對象作為一個(gè)基類對象對待。例如来氧,有這樣一個(gè)設(shè)計(jì):一個(gè)Dog類型的對象派生自Animal類诫给,這是模擬"是一個(gè)(is-a)"關(guān)系(例圖,Dog是一個(gè)Animal)啦扬。實(shí)例化:創(chuàng)建一個(gè)類的實(shí)例中狂,類的具體對象。方法:類中定義的函數(shù)扑毡。對象:通過類定義的數(shù)據(jù)結(jié)構(gòu)實(shí)例胃榕。對象包括兩個(gè)數(shù)據(jù)成員(類變量和實(shí)例變量)和方法。創(chuàng)建類使用class語句來創(chuàng)建一個(gè)新類瞄摊,class之后為類的名稱并以冒號結(jié)尾勋又,如下實(shí)例:class ClassName: '類的幫助信息' #類文檔字符串 class_suite #類體類的幫助信息可以通過ClassName.__doc__查看苦掘。class_suite 由類成員,方法楔壤,數(shù)據(jù)屬性組成鹤啡。實(shí)例以下是一個(gè)簡單的Python類實(shí)例:實(shí)例#!/usr/bin/python# -*- coding: UTF-8 -*- class Employee: '所有員工的基類' empCount = 0 def __init__(self, name, salary): self.name = name self.salary = salary Employee.empCount += 1 def displayCount(self): print "Total Employee %d" % Employee.empCount def displayEmployee(self): print "Name : ", self.name, ", Salary: ", self.salaryempCount 變量是一個(gè)類變量,它的值將在這個(gè)類的所有實(shí)例之間共享挺邀。你可以在內(nèi)部類或外部類使用 Employee.empCount 訪問。第一種方法__init__()方法是一種特殊的方法跳座,被稱為類的構(gòu)造函數(shù)或初始化方法端铛,當(dāng)創(chuàng)建了這個(gè)類的實(shí)例時(shí)就會調(diào)用該方法self 代表類的實(shí)例,self 在定義類的方法時(shí)是必須有的疲眷,雖然在調(diào)用時(shí)不必傳入相應(yīng)的參數(shù)禾蚕。self代表類的實(shí)例,而非類類的方法與普通的函數(shù)只有一個(gè)特別的區(qū)別——它們必須有一個(gè)額外的第一個(gè)參數(shù)名稱, 按照慣例它的名稱是 self狂丝。class Test: def prt(self): print(self) print(self.__class__) t = Test()t.prt()以上實(shí)例執(zhí)行結(jié)果為:<__main__.Test instance at 0x10d066878>__main__.Test從執(zhí)行結(jié)果可以很明顯的看出换淆,self 代表的是類的實(shí)例,代表當(dāng)前對象的地址几颜,而 self.class 則指向類倍试。self 不是 python 關(guān)鍵字,我們把他換成 runoob 也是可以正常執(zhí)行的:實(shí)例class Test: def prt(runoob): print(runoob) print(runoob.__class__) t = Test()t.prt()以上實(shí)例執(zhí)行結(jié)果為:<__main__.Test instance at 0x10d066878>__main__.Test創(chuàng)建實(shí)例對象實(shí)例化類其他編程語言中一般用關(guān)鍵字 new蛋哭,但是在 Python 中并沒有這個(gè)關(guān)鍵字县习,類的實(shí)例化類似函數(shù)調(diào)用方式。以下使用類的名稱 Employee 來實(shí)例化谆趾,并通過 __init__ 方法接受參數(shù)躁愿。"創(chuàng)建 Employee 類的第一個(gè)對象"emp1 = Employee("Zara", 2000)"創(chuàng)建 Employee 類的第二個(gè)對象"emp2 = Employee("Manni", 5000)訪問屬性您可以使用點(diǎn)(.)來訪問對象的屬性。使用如下類的名稱訪問類變量:emp1.displayEmployee()emp2.displayEmployee()print "Total Employee %d" % Employee.empCount完整實(shí)例:實(shí)例#!/usr/bin/python# -*- coding: UTF-8 -*- class Employee: '所有員工的基類' empCount = 0 def __init__(self, name, salary): self.name = name self.salary = salary Employee.empCount += 1 def displayCount(self): print "Total Employee %d" % Employee.empCount def displayEmployee(self): print "Name : ", self.name, ", Salary: ", self.salary "創(chuàng)建 Employee 類的第一個(gè)對象"emp1 = Employee("Zara", 2000)"創(chuàng)建 Employee 類的第二個(gè)對象"emp2 = Employee("Manni", 5000)emp1.displayEmployee()emp2.displayEmployee()print "Total Employee %d" % Employee.empCount執(zhí)行以上代碼輸出結(jié)果如下:Name : Zara ,Salary: 2000Name : Manni ,Salary: 5000Total Employee 2你可以添加沪蓬,刪除彤钟,修改類的屬性,如下所示:emp1.age = 7 # 添加一個(gè) 'age' 屬性emp1.age = 8 # 修改 'age' 屬性del emp1.age # 刪除 'age' 屬性你也可以使用以下函數(shù)的方式來訪問屬性:getattr(obj, name[, default]) : 訪問對象的屬性跷叉。hasattr(obj,name) : 檢查是否存在一個(gè)屬性逸雹。setattr(obj,name,value) : 設(shè)置一個(gè)屬性。如果屬性不存在云挟,會創(chuàng)建一個(gè)新屬性峡眶。delattr(obj, name) : 刪除屬性。hasattr(emp1, 'age') # 如果存在 'age' 屬性返回 True植锉。getattr(emp1, 'age') # 返回 'age' 屬性的值setattr(emp1, 'age', 8) # 添加屬性 'age' 值為 8delattr(empl, 'age') # 刪除屬性 'age'Python內(nèi)置類屬性__dict__ : 類的屬性(包含一個(gè)字典辫樱,由類的數(shù)據(jù)屬性組成)__doc__ :類的文檔字符串__name__: 類名__module__: 類定義所在的模塊(類的全名是'__main__.className',如果類位于一個(gè)導(dǎo)入模塊mymod中俊庇,那么className.__module__ 等于 mymod)__bases__ : 類的所有父類構(gòu)成元素(包含了一個(gè)由所有父類組成的元組)Python內(nèi)置類屬性調(diào)用實(shí)例如下:實(shí)例#!/usr/bin/python# -*- coding: UTF-8 -*- class Employee: '所有員工的基類' empCount = 0 def __init__(self, name, salary): self.name = name self.salary = salary Employee.empCount += 1 def displayCount(self): print "Total Employee %d" % Employee.empCount def displayEmployee(self): print "Name : ", self.name, ", Salary: ", self.salary print "Employee.__doc__:", Employee.__doc__print "Employee.__name__:", Employee.__name__print "Employee.__module__:", Employee.__module__print "Employee.__bases__:", Employee.__bases__print "Employee.__dict__:", Employee.__dict__執(zhí)行以上代碼輸出結(jié)果如下:Employee.__doc__: 所有員工的基類Employee.__name__: EmployeeEmployee.__module__: __main__Employee.__bases__: ()Employee.__dict__: {'__module__': '__main__', 'displayCount':, 'empCount': 0, 'displayEmployee':, '__doc__': '\xe6\x89\x80\xe6\x9c\x89\xe5\x91\x98\xe5\xb7\xa5\xe7\x9a\x84\xe5\x9f\xba\xe7\xb1\xbb', '__init__':}python對象銷毀(垃圾回收)Python 使用了引用計(jì)數(shù)這一簡單技術(shù)來跟蹤和回收垃圾狮暑。在 Python 內(nèi)部記錄著所有使用中的對象各有多少引用鸡挠。一個(gè)內(nèi)部跟蹤變量,稱為一個(gè)引用計(jì)數(shù)器搬男。當(dāng)對象被創(chuàng)建時(shí)拣展, 就創(chuàng)建了一個(gè)引用計(jì)數(shù), 當(dāng)這個(gè)對象不再需要時(shí)缔逛, 也就是說备埃, 這個(gè)對象的引用計(jì)數(shù)變?yōu)? 時(shí), 它被垃圾回收褐奴。但是回收不是"立即"的按脚, 由解釋器在適當(dāng)?shù)臅r(shí)機(jī),將垃圾對象占用的內(nèi)存空間回收敦冬。a = 40 # 創(chuàng)建對象 <40>b = a # 增加引用辅搬, <40> 的計(jì)數(shù)c = [b] # 增加引用. <40> 的計(jì)數(shù)del a # 減少引用 <40> 的計(jì)數(shù)b = 100 # 減少引用 <40> 的計(jì)數(shù)c[0] = -1 # 減少引用 <40> 的計(jì)數(shù)垃圾回收機(jī)制不僅針對引用計(jì)數(shù)為0的對象,同樣也可以處理循環(huán)引用的情況脖旱。循環(huán)引用指的是堪遂,兩個(gè)對象相互引用,但是沒有其他變量引用他們萌庆。這種情況下溶褪,僅使用引用計(jì)數(shù)是不夠的。Python 的垃圾收集器實(shí)際上是一個(gè)引用計(jì)數(shù)器和一個(gè)循環(huán)垃圾收集器践险。作為引用計(jì)數(shù)的補(bǔ)充竿滨, 垃圾收集器也會留心被分配的總量很大(及未通過引用計(jì)數(shù)銷毀的那些)的對象。 在這種情況下捏境, 解釋器會暫停下來于游, 試圖清理所有未引用的循環(huán)。實(shí)例析構(gòu)函數(shù) __del__ 垫言,__del__在對象銷毀的時(shí)候被調(diào)用贰剥,當(dāng)對象不再被使用時(shí),__del__方法運(yùn)行:實(shí)例#!/usr/bin/python# -*- coding: UTF-8 -*- class Point: def __init__( self, x=0, y=0): self.x = x self.y = y def __del__(self): class_name = self.__class__.__name__ print class_name, "銷毀" pt1 = Point()pt2 = pt1pt3 = pt1print id(pt1), id(pt2), id(pt3) # 打印對象的iddel pt1del pt2del pt3以上實(shí)例運(yùn)行結(jié)果如下:3083401324 3083401324 3083401324Point 銷毀注意:通常你需要在單獨(dú)的文件中定義一個(gè)類筷频,類的繼承面向?qū)ο蟮木幊處淼闹饕锰幹皇谴a的重用蚌成,實(shí)現(xiàn)這種重用的方法之一是通過繼承機(jī)制。繼承完全可以理解成類之間的類型和子類型關(guān)系凛捏。需要注意的地方:繼承語法 class 派生類名(基類名)://... 基類名寫在括號里担忧,基本類是在類定義的時(shí)候旦签,在元組之中指明的桃焕。在python中繼承中的一些特點(diǎn):1:在繼承中基類的構(gòu)造(__init__()方法)不會被自動(dòng)調(diào)用,它需要在其派生類的構(gòu)造中親自專門調(diào)用呕乎。2:在調(diào)用基類的方法時(shí),需要加上基類的類名前綴惩猫,且需要帶上self參數(shù)變量芝硬。區(qū)別于在類中調(diào)用普通函數(shù)時(shí)并不需要帶上self參數(shù)3:Python總是首先查找對應(yīng)類型的方法,如果它不能在派生類中找到對應(yīng)的方法轧房,它才開始到基類中逐個(gè)查找拌阴。(先在本類中查找調(diào)用的方法,找不到才去基類中找)奶镶。如果在繼承元組中列了一個(gè)以上的類迟赃,那么它就被稱作"多重繼承" 。語法:派生類的聲明厂镇,與他們的父類類似纤壁,繼承的基類列表跟在類名之后,如下所示:class SubClassName (ParentClass1[, ParentClass2, ...]): 'Optional class documentation string' class_suite實(shí)例#!/usr/bin/python# -*- coding: UTF-8 -*- class Parent: # 定義父類 parentAttr = 100 def __init__(self): print "調(diào)用父類構(gòu)造函數(shù)" def parentMethod(self): print '調(diào)用父類方法' def setAttr(self, attr): Parent.parentAttr = attr def getAttr(self): print "父類屬性 :", Parent.parentAttr class Child(Parent): # 定義子類 def __init__(self): print "調(diào)用子類構(gòu)造方法" def childMethod(self): print '調(diào)用子類方法' c = Child() # 實(shí)例化子類c.childMethod() # 調(diào)用子類的方法c.parentMethod() # 調(diào)用父類方法c.setAttr(200) # 再次調(diào)用父類的方法 - 設(shè)置屬性值c.getAttr() # 再次調(diào)用父類的方法 - 獲取屬性值以上代碼執(zhí)行結(jié)果如下:調(diào)用子類構(gòu)造方法調(diào)用子類方法調(diào)用父類方法父類屬性 : 200你可以繼承多個(gè)類class A: # 定義類 A.....class B: # 定義類 B.....class C(A, B): # 繼承類 A 和 B.....你可以使用issubclass()或者isinstance()方法來檢測剪撬。issubclass() - 布爾函數(shù)判斷一個(gè)類是另一個(gè)類的子類或者子孫類摄乒,語法:issubclass(sub,sup)isinstance(obj, Class) 布爾函數(shù)如果obj是Class類的實(shí)例對象或者是一個(gè)Class子類的實(shí)例對象則返回true悠反。方法重寫如果你的父類方法的功能不能滿足你的需求残黑,你可以在子類重寫你父類的方法:實(shí)例:實(shí)例#!/usr/bin/python# -*- coding: UTF-8 -*- class Parent: # 定義父類 def myMethod(self): print '調(diào)用父類方法' class Child(Parent): # 定義子類 def myMethod(self): print '調(diào)用子類方法' c = Child() # 子類實(shí)例c.myMethod() # 子類調(diào)用重寫方法執(zhí)行以上代碼輸出結(jié)果如下:調(diào)用子類方法基礎(chǔ)重載方法下表列出了一些通用的功能,你可以在自己的類重寫:運(yùn)算符重載Python同樣支持運(yùn)算符重載斋否,實(shí)例如下:實(shí)例#!/usr/bin/python class Vector: def __init__(self, a, b): self.a = a self.b = b def __str__(self): return 'Vector (%d, %d)' % (self.a, self.b) def __add__(self,other): return Vector(self.a + other.a, self.b + other.b) v1 = Vector(2,10)v2 = Vector(5,-2)print v1 + v2以上代碼執(zhí)行結(jié)果如下所示:Vector(7,8)類屬性與方法類的私有屬性__private_attrs:兩個(gè)下劃線開頭梨水,聲明該屬性為私有,不能在類的外部被使用或直接訪問茵臭。在類內(nèi)部的方法中使用時(shí) self.__private_attrs疫诽。類的方法在類的內(nèi)部,使用 def 關(guān)鍵字可以為類定義一個(gè)方法旦委,與一般函數(shù)定義不同奇徒,類方法必須包含參數(shù) self,且為第一個(gè)參數(shù)類的私有方法__private_method:兩個(gè)下劃線開頭,聲明該方法為私有方法缨硝,不能在類地外部調(diào)用摩钙。在類的內(nèi)部調(diào)用 self.__private_methods實(shí)例#!/usr/bin/python# -*- coding: UTF-8 -*- class JustCounter: __secretCount = 0 # 私有變量 publicCount = 0 # 公開變量 def count(self): self.__secretCount += 1 self.publicCount += 1 print self.__secretCount counter = JustCounter()counter.count()counter.count()print counter.publicCountprint counter.__secretCount # 報(bào)錯(cuò),實(shí)例不能訪問私有變量Python 通過改變名稱來包含類名:122Traceback (most recent call last): File "test.py", line 17, inprint counter.__secretCount # 報(bào)錯(cuò)查辩,實(shí)例不能訪問私有變量AttributeError: JustCounter instance has no attribute '__secretCount'Python不允許實(shí)例化的類訪問私有數(shù)據(jù)胖笛,但你可以使用 object._className__attrName 訪問屬性,將如下代碼替換以上代碼的最后一行代碼:.........................print counter._JustCounter__secretCount執(zhí)行以上代碼宜岛,執(zhí)行結(jié)果如下:1222單下劃線长踊、雙下劃線、頭尾雙下劃線說明:__foo__: 定義的是特列方法萍倡,類似 __init__() 之類的身弊。_foo: 以單下劃線開頭的表示的是 protected 類型的變量,即保護(hù)類型只能允許其本身與子類進(jìn)行訪問,不能用于 from module import *__foo: 雙下劃線的表示的是私有類型(private)的變量, 只能是允許這個(gè)類本身進(jìn)行訪問了佑刷。Python正則表達(dá)式正則表達(dá)式是一個(gè)特殊的字符序列莉擒,它能幫助你方便的檢查一個(gè)字符串是否與某種模式匹配。Python 自1.5版本起增加了re 模塊瘫絮,它提供 Perl 風(fēng)格的正則表達(dá)式模式涨冀。re 模塊使 Python 語言擁有全部的正則表達(dá)式功能。compile 函數(shù)根據(jù)一個(gè)模式字符串和可選的標(biāo)志參數(shù)生成一個(gè)正則表達(dá)式對象麦萤。該對象擁有一系列方法用于正則表達(dá)式匹配和替換鹿鳖。re 模塊也提供了與這些方法功能完全一致的函數(shù),這些函數(shù)使用一個(gè)模式字符串做為它們的第一個(gè)參數(shù)壮莹。本章節(jié)主要介紹Python中常用的正則表達(dá)式處理函數(shù)翅帜。re.match函數(shù)re.match 嘗試從字符串的起始位置匹配一個(gè)模式,如果不是起始位置匹配成功的話命满,match()就返回none涝滴。函數(shù)語法:re.match(pattern, string, flags=0)函數(shù)參數(shù)說明:匹配成功re.match方法返回一個(gè)匹配的對象,否則返回None胶台。我們可以使用group(num) 或 groups() 匹配對象函數(shù)來獲取匹配表達(dá)式歼疮。實(shí)例 1#!/usr/bin/python# -*- coding: UTF-8 -*- import reprint(re.match('www', 'www.runoob.com').span()) # 在起始位置匹配print(re.match('com', 'www.runoob.com')) # 不在起始位置匹配以上實(shí)例運(yùn)行輸出結(jié)果為:(0, 3)None實(shí)例 2#!/usr/bin/pythonimport re line = "Cats are smarter than dogs" matchObj = re.match( r'(.*) are (.*?) .*', line, re.M|re.I) if matchObj: print "matchObj.group() : ", matchObj.group() print "matchObj.group(1) : ", matchObj.group(1) print "matchObj.group(2) : ", matchObj.group(2)else: print "No match!!"以上實(shí)例執(zhí)行結(jié)果如下:matchObj.group() : Cats are smarter than dogsmatchObj.group(1) : CatsmatchObj.group(2) : smarterre.search方法re.search 掃描整個(gè)字符串并返回第一個(gè)成功的匹配。函數(shù)語法:re.search(pattern, string, flags=0)函數(shù)參數(shù)說明:匹配成功re.search方法返回一個(gè)匹配的對象诈唬,否則返回None韩脏。我們可以使用group(num) 或 groups() 匹配對象函數(shù)來獲取匹配表達(dá)式。實(shí)例 1#!/usr/bin/python# -*- coding: UTF-8 -*- import reprint(re.search('www', 'www.runoob.com').span()) # 在起始位置匹配print(re.search('com', 'www.runoob.com').span()) # 不在起始位置匹配以上實(shí)例運(yùn)行輸出結(jié)果為:(0, 3)(11, 14)實(shí)例 2#!/usr/bin/pythonimport re line = "Cats are smarter than dogs"; searchObj = re.search( r'(.*) are (.*?) .*', line, re.M|re.I) if searchObj: print "searchObj.group() : ", searchObj.group() print "searchObj.group(1) : ", searchObj.group(1) print "searchObj.group(2) : ", searchObj.group(2)else: print "Nothing found!!"以上實(shí)例執(zhí)行結(jié)果如下:searchObj.group() : Cats are smarter than dogssearchObj.group(1) : CatssearchObj.group(2) : smarterre.match與re.search的區(qū)別re.match只匹配字符串的開始铸磅,如果字符串開始不符合正則表達(dá)式赡矢,則匹配失敗,函數(shù)返回None阅仔;而re.search匹配整個(gè)字符串吹散,直到找到一個(gè)匹配。實(shí)例#!/usr/bin/pythonimport re line = "Cats are smarter than dogs"; matchObj = re.match( r'dogs', line, re.M|re.I)if matchObj: print "match --> matchObj.group() : ", matchObj.group()else: print "No match!!" matchObj = re.search( r'dogs', line, re.M|re.I)if matchObj: print "search --> matchObj.group() : ", matchObj.group()else: print "No match!!"以上實(shí)例運(yùn)行結(jié)果如下:No match!!search --> matchObj.group() : dogs檢索和替換Python 的 re 模塊提供了re.sub用于替換字符串中的匹配項(xiàng)八酒。語法:re.sub(pattern, repl, string, count=0, flags=0)參數(shù):pattern : 正則中的模式字符串空民。repl : 替換的字符串,也可為一個(gè)函數(shù)丘跌。string : 要被查找替換的原始字符串袭景。count : 模式匹配后替換的最大次數(shù),默認(rèn) 0 表示替換所有的匹配闭树。實(shí)例#!/usr/bin/python# -*- coding: UTF-8 -*- import re phone = "2004-959-559 # 這是一個(gè)國外電話號碼" # 刪除字符串中的 Python注釋 num = re.sub(r'#.*$', "", phone)print "電話號碼是: ", num # 刪除非數(shù)字(-)的字符串 num = re.sub(r'\D', "", phone)print "電話號碼是 : ", num以上實(shí)例執(zhí)行結(jié)果如下:電話號碼是: 2004-959-559 電話號碼是 : 2004959559repl 參數(shù)是一個(gè)函數(shù)以下實(shí)例中將字符串中的匹配的數(shù)字乘于 2:實(shí)例#!/usr/bin/python# -*- coding: UTF-8 -*- import re # 將匹配的數(shù)字乘于 2def double(matched): value = int(matched.group('value')) return str(value * 2) s = 'A23G4HFD567'print(re.sub('(?P\d+)', double, s))執(zhí)行輸出結(jié)果為:A46G8HFD1134正則表達(dá)式修飾符 - 可選標(biāo)志正則表達(dá)式可以包含一些可選標(biāo)志修飾符來控制匹配的模式耸棒。修飾符被指定為一個(gè)可選的標(biāo)志。多個(gè)標(biāo)志可以通過按位 OR(|) 它們來指定报辱。如 re.I | re.M 被設(shè)置成 I 和 M 標(biāo)志:正則表達(dá)式模式模式字符串使用特殊的語法來表示一個(gè)正則表達(dá)式:字母和數(shù)字表示他們自身与殃。一個(gè)正則表達(dá)式模式中的字母和數(shù)字匹配同樣的字符串。多數(shù)字母和數(shù)字前加一個(gè)反斜杠時(shí)會擁有不同的含義。標(biāo)點(diǎn)符號只有被轉(zhuǎn)義時(shí)才匹配自身幅疼,否則它們表示特殊的含義米奸。反斜杠本身需要使用反斜杠轉(zhuǎn)義。由于正則表達(dá)式通常都包含反斜杠爽篷,所以你最好使用原始字符串來表示它們悴晰。模式元素(如 r'\t',等價(jià)于 '\\t')匹配相應(yīng)的特殊字符逐工。下表列出了正則表達(dá)式模式語法中的特殊元素铡溪。如果你使用模式的同時(shí)提供了可選的標(biāo)志參數(shù),某些模式元素的含義會改變泪喊。正則表達(dá)式實(shí)例字符匹配字符類特殊字符類Python CGI編程什么是CGICGI 目前由NCSA維護(hù)棕硫,NCSA定義CGI如下:CGI(Common Gateway Interface),通用網(wǎng)關(guān)接口,它是一段程序,運(yùn)行在服務(wù)器上如:HTTP服務(wù)器,提供同客戶端HTML頁面的接口袒啼。網(wǎng)頁瀏覽為了更好的了解CGI是如何工作的哈扮,我們可以從在網(wǎng)頁上點(diǎn)擊一個(gè)鏈接或URL的流程:1、使用你的瀏覽器訪問URL并連接到HTTP web 服務(wù)器蚓再。2滑肉、Web服務(wù)器接收到請求信息后會解析URL,并查找訪問的文件在服務(wù)器上是否存在对途,如果存在返回文件的內(nèi)容赦邻,否則返回錯(cuò)誤信息髓棋。3实檀、瀏覽器從服務(wù)器上接收信息,并顯示接收的文件或者錯(cuò)誤信息按声。CGI程序可以是Python腳本膳犹,PERL腳本,SHELL腳本签则,C或者C++程序等须床。CGI架構(gòu)圖Web服務(wù)器支持及配置在你進(jìn)行CGI編程前,確保您的Web服務(wù)器支持CGI及已經(jīng)配置了CGI的處理程序渐裂。Apache 支持CGI 配置:設(shè)置好CGI目錄:ScriptAlias /cgi-bin/ /var/www/cgi-bin/所有的HTTP服務(wù)器執(zhí)行CGI程序都保存在一個(gè)預(yù)先配置的目錄豺旬。這個(gè)目錄被稱為CGI目錄,并按照慣例柒凉,它被命名為/var/www/cgi-bin目錄族阅。CGI文件的擴(kuò)展名為.cgi,python也可以使用.py擴(kuò)展名膝捞。默認(rèn)情況下坦刀,Linux服務(wù)器配置運(yùn)行的cgi-bin目錄中為/var/www。如果你想指定其他運(yùn)行 CGI 腳本的目錄,可以修改 httpd.conf 配置文件鲤遥,如下所示: AllowOverride None
? Options +ExecCGI
? Order allow,deny
? Allow from all在 AddHandler 中添加 .py 后綴沐寺,這樣我們就可以訪問 .py 結(jié)尾的 python 腳本文件:AddHandler cgi-script .cgi .pl .py第一個(gè)CGI程序我們使用Python創(chuàng)建第一個(gè)CGI程序,文件名為hello.py盖奈,文件位于/var/www/cgi-bin目錄中混坞,內(nèi)容如下:#!/usr/bin/python# -*- coding: UTF-8 -*-print "Content-type:text/html"print? ? ? ? ? ? ? ? ? ? ? ? ? ? ? # 空行,告訴服務(wù)器結(jié)束頭部print ''print ''print ''print '
Hello Word! 我是來自菜鳥教程的第一CGI程序
'print ''print ''文件保存后修改 hello.py钢坦,修改文件權(quán)限為 755:chmod 755 hello.py 以上程序在瀏覽器訪問顯示結(jié)果如下:這個(gè)的hello.py腳本是一個(gè)簡單的Python腳本拔第,腳本第一行的輸出內(nèi)容"Content-type:text/html"發(fā)送到瀏覽器并告知瀏覽器顯示的內(nèi)容類型為"text/html"。用 print 輸出一個(gè)空行用于告訴服務(wù)器結(jié)束頭部信息场钉。HTTP頭部hello.py文件內(nèi)容中的" Content-type:text/html"即為HTTP頭部的一部分蚊俺,它會發(fā)送給瀏覽器告訴瀏覽器文件的內(nèi)容類型。HTTP頭部的格式如下:HTTP 字段名: 字段內(nèi)容例如:Content-type: text/html以下表格介紹了CGI程序中HTTP頭部經(jīng)常使用的信息:CGI環(huán)境變量所有的CGI程序都接收以下的環(huán)境變量逛万,這些變量在CGI程序中發(fā)揮了重要的作用:以下是一個(gè)簡單的CGI腳本輸出CGI的環(huán)境變量:#!/usr/bin/python# -*- coding: UTF-8 -*-# filename:test.pyimport osprint "Content-type: text/html"printprint ""print "環(huán)境變量
";print "
"for key in os.environ.keys():? ? print "
%30s : %s
" % (key,os.environ[key])print "
"將以上點(diǎn)保存為 test.py ,并修改文件權(quán)限為 755泳猬,執(zhí)行結(jié)果如下:GET和POST方法瀏覽器客戶端通過兩種方法向服務(wù)器傳遞信息,這兩種方法就是 GET 方法和 POST 方法宇植。使用GET方法傳輸數(shù)據(jù)GET方法發(fā)送編碼后的用戶信息到服務(wù)端得封,數(shù)據(jù)信息包含在請求頁面的URL上,以"?"號分割, 如下所示:http://www.test.com/cgi-bin/hello.py?key1=value1&key2=value2有關(guān) GET 請求的其他一些注釋:GET 請求可被緩存GET 請求保留在瀏覽器歷史記錄中GET 請求可被收藏為書簽GET 請求不應(yīng)在處理敏感數(shù)據(jù)時(shí)使用GET 請求有長度限制GET 請求只應(yīng)當(dāng)用于取回?cái)?shù)據(jù)簡單的url實(shí)例:GET方法以下是一個(gè)簡單的URL指郁,使用GET方法向hello_get.py程序發(fā)送兩個(gè)參數(shù):/cgi-bin/test.py?name=菜鳥教程&url=http://www.runoob.com以下為hello_get.py文件的代碼:#!/usr/bin/python# -*- coding: UTF-8 -*-# filename:test.py# CGI處理模塊import cgi, cgitb # 創(chuàng)建 FieldStorage 的實(shí)例化form = cgi.FieldStorage() # 獲取數(shù)據(jù)site_name = form.getvalue('name')site_url? = form.getvalue('url')print "Content-type:text/html"printprint ""print ""print ""print "
%s官網(wǎng):%s
" % (site_name, site_url)print ""print ""文件保存后修改 hello_get.py忙上,修改文件權(quán)限為 755:chmod 755 hello_get.py 瀏覽器請求輸出結(jié)果:簡單的表單實(shí)例:GET方法以下是一個(gè)通過HTML的表單使用GET方法向服務(wù)器發(fā)送兩個(gè)數(shù)據(jù),提交的服務(wù)器腳本同樣是hello_get.py文件闲坎,hello_get.html 代碼如下:
站點(diǎn)名稱:
站點(diǎn) URL:
默認(rèn)情況下 cgi-bin 目錄只能存放腳本文件疫粥,我們將 hello_get.html 存儲在 test 目錄下,修改文件權(quán)限為 755:chmod 755 hello_get.htmlGif 演示如下所示:使用POST方法傳遞數(shù)據(jù)使用POST方法向服務(wù)器傳遞數(shù)據(jù)是更安全可靠的腰懂,像一些敏感信息如用戶密碼等需要使用POST傳輸數(shù)據(jù)梗逮。以下同樣是hello_get.py ,它也可以處理瀏覽器提交的POST表單數(shù)據(jù):#!/usr/bin/python# -*- coding: UTF-8 -*-# CGI處理模塊import cgi, cgitb # 創(chuàng)建 FieldStorage 的實(shí)例化form = cgi.FieldStorage() # 獲取數(shù)據(jù)site_name = form.getvalue('name')site_url? = form.getvalue('url')print "Content-type:text/html"printprint ""print ""print ""print "
%s官網(wǎng):%s
" % (site_name, site_url)print ""print ""以下為表單通過POST方法(method="post")向服務(wù)器腳本 hello_get.py 提交數(shù)據(jù):
站點(diǎn)名稱:
站點(diǎn) URL:
Gif 演示如下所示:通過CGI程序傳遞checkbox數(shù)據(jù)checkbox用于提交一個(gè)或者多個(gè)選項(xiàng)數(shù)據(jù)绣溜,HTML代碼如下:
菜鳥教程Google
以下為 checkbox.py 文件的代碼:#!/usr/bin/python# -*- coding: UTF-8 -*-# 引入 CGI 處理模塊 import cgi, cgitb # 創(chuàng)建 FieldStorage的實(shí)例 form = cgi.FieldStorage() # 接收字段數(shù)據(jù)if form.getvalue('google'):? google_flag = "是"else:? google_flag = "否"if form.getvalue('runoob'):? runoob_flag = "是"else:? runoob_flag = "否"print "Content-type:text/html"printprint ""print ""print ""print "
菜鳥教程是否選擇了 : %s
" % runoob_flagprint "
Google 是否選擇了 : %s
" % google_flagprint ""print ""修改 checkbox.py 權(quán)限:chmod 755 checkbox.py瀏覽器訪問 Gif 演示圖:通過CGI程序傳遞Radio數(shù)據(jù)Radio 只向服務(wù)器傳遞一個(gè)數(shù)據(jù)慷彤,HTML代碼如下:
菜鳥教程Google
radiobutton.py 腳本代碼如下:#!/usr/bin/python# -*- coding: UTF-8 -*-# 引入 CGI 處理模塊 import cgi, cgitb # 創(chuàng)建 FieldStorage的實(shí)例 form = cgi.FieldStorage() # 接收字段數(shù)據(jù)if form.getvalue('site'):? site = form.getvalue('site')else:? site = "提交數(shù)據(jù)為空"print "Content-type:text/html"printprint ""print ""print ""print "
選中的網(wǎng)站是 %s
" % siteprint ""print ""修改 radiobutton.py 權(quán)限:chmod 755 radiobutton.py瀏覽器訪問 Gif 演示圖:通過CGI程序傳遞 Textarea 數(shù)據(jù)Textarea 向服務(wù)器傳遞多行數(shù)據(jù),HTML代碼如下:
在這里輸入內(nèi)容...
textarea.py 腳本代碼如下:#!/usr/bin/python# -*- coding: UTF-8 -*-# 引入 CGI 處理模塊 import cgi, cgitb # 創(chuàng)建 FieldStorage的實(shí)例 form = cgi.FieldStorage() # 接收字段數(shù)據(jù)if form.getvalue('textcontent'):? text_content = form.getvalue('textcontent')else:? text_content = "沒有內(nèi)容"print "Content-type:text/html"printprint ""print ""print ""print "
輸入的內(nèi)容是:%s
" % text_contentprint ""print ""修改 textarea.py 權(quán)限:chmod 755 textarea.py瀏覽器訪問 Gif 演示圖:通過CGI程序傳遞下拉數(shù)據(jù)怖喻。HTML 下拉框代碼如下:
菜鳥教程Google
dropdown.py 腳本代碼如下所示:#!/usr/bin/python# -*- coding: UTF-8 -*-# 引入 CGI 處理模塊 import cgi, cgitb # 創(chuàng)建 FieldStorage的實(shí)例 form = cgi.FieldStorage() # 接收字段數(shù)據(jù)if form.getvalue('dropdown'):? dropdown_value = form.getvalue('dropdown')else:? dropdown_value = "沒有內(nèi)容"print "Content-type:text/html"printprint ""print ""print ""print "
選中的選項(xiàng)是:%s
" % dropdown_valueprint ""print ""修改 dropdown.py 權(quán)限:chmod 755 dropdown.py瀏覽器訪問 Gif 演示圖:CGI中使用Cookie在 http 協(xié)議一個(gè)很大的缺點(diǎn)就是不對用戶身份的進(jìn)行判斷底哗,這樣給編程人員帶來很大的不便, 而 cookie 功能的出現(xiàn)彌補(bǔ)了這個(gè)不足锚沸。cookie 就是在客戶訪問腳本的同時(shí)跋选,通過客戶的瀏覽器,在客戶硬盤上寫入紀(jì)錄數(shù)據(jù) 咒吐,當(dāng)下次客戶訪問腳本時(shí)取回?cái)?shù)據(jù)信息野建,從而達(dá)到身份判別的功能属划,cookie 常用在身份校驗(yàn)中『蛏 cookie的語法http cookie的發(fā)送是通過http頭部來實(shí)現(xiàn)的同眯,他早于文件的傳遞,頭部set-cookie的語法如下:Set-cookie:name=name;expires=date;path=path;domain=domain;secure name=name: 需要設(shè)置cookie的值(name不能使用";"和","號),有多個(gè)name值時(shí)用 ";" 分隔唯鸭,例如:name1=name1;name2=name2;name3=name3须蜗。expires=date: cookie的有效期限,格式: expires="Wdy,DD-Mon-YYYY HH:MM:SS"path=path: 設(shè)置cookie支持的路徑,如果path是一個(gè)路徑,則cookie對這個(gè)目錄下的所有文件及子目錄生效目溉,例如: path="/cgi-bin/"明肮,如果path是一個(gè)文件,則cookie指對這個(gè)文件生效缭付,例如:path="/cgi-bin/cookie.cgi"柿估。domain=domain: 對cookie生效的域名,例如:domain="www.runoob.com"secure: 如果給出此標(biāo)志陷猫,表示cookie只能通過SSL協(xié)議的https服務(wù)器來傳遞秫舌。cookie的接收是通過設(shè)置環(huán)境變量HTTP_COOKIE來實(shí)現(xiàn)的,CGI程序可以通過檢索該變量獲取cookie信息绣檬。Cookie設(shè)置Cookie的設(shè)置非常簡單足陨,cookie會在http頭部單獨(dú)發(fā)送。以下實(shí)例在cookie中設(shè)置了name 和 expires:#!/usr/bin/python# -*- coding: UTF-8 -*-# print 'Content-Type: text/html'print 'Set-Cookie: name="菜鳥教程";expires=Wed, 28 Aug 2016 18:30:00 GMT'printprint """
Cookie set OK!
"""將以上代碼保存到 cookie_set.py娇未,并修改 cookie_set.py 權(quán)限:chmod 755 cookie_set.py以上實(shí)例使用了 Set-Cookie 頭信息來設(shè)置Cookie信息墨缘,可選項(xiàng)中設(shè)置了Cookie的其他屬性,如過期時(shí)間Expires零抬,域名Domain镊讼,路徑Path。這些信息設(shè)置在 "Content-type:text/html"之前媚值。檢索Cookie信息Cookie信息檢索頁非常簡單狠毯,Cookie信息存儲在CGI的環(huán)境變量HTTP_COOKIE中护糖,存儲格式如下:key1=value1;key2=value2;key3=value3....以下是一個(gè)簡單的CGI檢索cookie信息的程序:#!/usr/bin/python# -*- coding: UTF-8 -*-# 導(dǎo)入模塊import osimport Cookieprint "Content-type: text/html"printprint """
讀取cookie信息
"""if 'HTTP_COOKIE' in os.environ:? ? cookie_string=os.environ.get('HTTP_COOKIE')? ? c=Cookie.SimpleCookie()? ? c.load(cookie_string)? ? try:? ? ? ? data=c['name'].value? ? ? ? print "cookie data: "+data+"
"? ? except KeyError:? ? ? ? print "cookie 沒有設(shè)置或者已過去
"print """"""將以上代碼保存到 cookie_get.py褥芒,并修改 cookie_get.py 權(quán)限:chmod 755 cookie_get.py以上 cookie 設(shè)置顏色 Gif 如下所示:文件上傳實(shí)例HTML設(shè)置上傳文件的表單需要設(shè)置 enctype 屬性為 multipart/form-data,代碼如下所示:
選中文件:
save_file.py腳本文件代碼如下:#!/usr/bin/python# -*- coding: UTF-8 -*-import cgi, osimport cgitb; cgitb.enable()form = cgi.FieldStorage()# 獲取文件名fileitem = form['filename']# 檢測文件是否上傳if fileitem.filename:? # 設(shè)置文件路徑? ? fn = os.path.basename(fileitem.filename)? open('/tmp/' + fn, 'wb').write(fileitem.file.read())? message = '文件 "' + fn + '" 上傳成功'? else:? message = '文件沒有上傳'? print """\Content-Type: text/html\n
%s
""" % (message,)將以上代碼保存到 save_file.py嫡良,并修改 save_file.py 權(quán)限:chmod 755 save_file.py以上 cookie 設(shè)置顏色 Gif 如下所示:如果你使用的系統(tǒng)是Unix/Linux锰扶,你必須替換文件分隔符,在window下只需要使用open()語句即可:fn = os.path.basename(fileitem.filename.replace("\\", "/" ))文件下載對話框我們先在當(dāng)前目錄下創(chuàng)建 foo.txt 文件寝受,用于程序的下載坷牛。文件下載通過設(shè)置HTTP頭信息來實(shí)現(xiàn),功能代碼如下:#!/usr/bin/python# -*- coding: UTF-8 -*-# HTTP 頭部print "Content-Disposition: attachment; filename=\"foo.txt\"";print# 打開文件fo = open("foo.txt", "rb")str = fo.read();print str# 關(guān)閉文件fo.close()python操作mysql數(shù)據(jù)庫Python 標(biāo)準(zhǔn)數(shù)據(jù)庫接口為 Python DB-API很澄,Python DB-API為開發(fā)人員提供了數(shù)據(jù)庫應(yīng)用編程接口京闰。Python 數(shù)據(jù)庫接口支持非常多的數(shù)據(jù)庫颜及,你可以選擇適合你項(xiàng)目的數(shù)據(jù)庫:GadFlymSQLMySQLPostgreSQLMicrosoft SQL Server 2000InformixInterbaseOracleSybase你可以訪問Python數(shù)據(jù)庫接口及API查看詳細(xì)的支持?jǐn)?shù)據(jù)庫列表。不同的數(shù)據(jù)庫你需要下載不同的DB API模塊蹂楣,例如你需要訪問Oracle數(shù)據(jù)庫和Mysql數(shù)據(jù)俏站,你需要下載Oracle和MySQL數(shù)據(jù)庫模塊。DB-API 是一個(gè)規(guī)范. 它定義了一系列必須的對象和數(shù)據(jù)庫存取方式, 以便為各種各樣的底層數(shù)據(jù)庫系統(tǒng)和多種多樣的數(shù)據(jù)庫接口程序提供一致的訪問接口 痊土。Python的DB-API肄扎,為大多數(shù)的數(shù)據(jù)庫實(shí)現(xiàn)了接口,使用它連接各數(shù)據(jù)庫后赁酝,就可以用相同的方式操作各數(shù)據(jù)庫犯祠。Python DB-API使用流程:引入 API 模塊。獲取與數(shù)據(jù)庫的連接酌呆。執(zhí)行SQL語句和存儲過程衡载。關(guān)閉數(shù)據(jù)庫連接。什么是MySQLdb?MySQLdb 是用于Python鏈接Mysql數(shù)據(jù)庫的接口隙袁,它實(shí)現(xiàn)了 Python 數(shù)據(jù)庫 API 規(guī)范 V2.0月劈,基于 MySQL C API 上建立的。如何安裝MySQLdb?為了用DB-API編寫MySQL腳本藤乙,必須確保已經(jīng)安裝了MySQL猜揪。復(fù)制以下代碼,并執(zhí)行:#!/usr/bin/python# -*- coding: UTF-8 -*-import MySQLdb如果執(zhí)行后的輸出結(jié)果如下所示坛梁,意味著你沒有安裝 MySQLdb 模塊:Traceback (most recent call last):? File "test.py", line 3, inimport MySQLdbImportError: No module named MySQLdb安裝MySQLdb而姐,請?jiān)L問 http://sourceforge.net/projects/mysql-python ,(Linux平臺可以訪問:https://pypi.python.org/pypi/MySQL-python)從這里可選擇適合您的平臺的安裝包划咐,分為預(yù)編譯的二進(jìn)制文件和源代碼安裝包拴念。如果您選擇二進(jìn)制文件發(fā)行版本的話,安裝過程基本安裝提示即可完成褐缠。如果從源代碼進(jìn)行安裝的話政鼠,則需要切換到MySQLdb發(fā)行版本的頂級目錄,并鍵入下列命令:$ gunzip MySQL-python-1.2.2.tar.gz$ tar -xvf MySQL-python-1.2.2.tar$ cd MySQL-python-1.2.2$ python setup.py build$ python setup.py install注意:請確保您有root權(quán)限來安裝上述模塊队魏。數(shù)據(jù)庫連接連接數(shù)據(jù)庫前公般,請先確認(rèn)以下事項(xiàng):您已經(jīng)創(chuàng)建了數(shù)據(jù)庫 TESTDB.在TESTDB數(shù)據(jù)庫中您已經(jīng)創(chuàng)建了表 EMPLOYEEEMPLOYEE表字段為 FIRST_NAME, LAST_NAME, AGE, SEX 和 INCOME。連接數(shù)據(jù)庫TESTDB使用的用戶名為 "testuser" 胡桨,密碼為 "test123",你可以可以自己設(shè)定或者直接使用root用戶名及其密碼官帘,Mysql數(shù)據(jù)庫用戶授權(quán)請使用Grant命令。在你的機(jī)子上已經(jīng)安裝了 Python MySQLdb 模塊昧谊。如果您對sql語句不熟悉刽虹,可以訪問我們的 SQL基礎(chǔ)教程實(shí)例:以下實(shí)例鏈接Mysql的TESTDB數(shù)據(jù)庫:#!/usr/bin/python# -*- coding: UTF-8 -*-import MySQLdb# 打開數(shù)據(jù)庫連接db = MySQLdb.connect("localhost","testuser","test123","TESTDB" )# 使用cursor()方法獲取操作游標(biāo) cursor = db.cursor()# 使用execute方法執(zhí)行SQL語句cursor.execute("SELECT VERSION()")# 使用 fetchone() 方法獲取一條數(shù)據(jù)data = cursor.fetchone()print "Database version : %s " % data# 關(guān)閉數(shù)據(jù)庫連接db.close()執(zhí)行以上腳本輸出結(jié)果如下:Database version : 5.0.45創(chuàng)建數(shù)據(jù)庫表如果數(shù)據(jù)庫連接存在我們可以使用execute()方法來為數(shù)據(jù)庫創(chuàng)建表,如下所示創(chuàng)建表EMPLOYEE:#!/usr/bin/python# -*- coding: UTF-8 -*-import MySQLdb# 打開數(shù)據(jù)庫連接db = MySQLdb.connect("localhost","testuser","test123","TESTDB" )# 使用cursor()方法獲取操作游標(biāo) cursor = db.cursor()# 如果數(shù)據(jù)表已經(jīng)存在使用 execute() 方法刪除表呢诬。cursor.execute("DROP TABLE IF EXISTS EMPLOYEE")# 創(chuàng)建數(shù)據(jù)表SQL語句sql = """CREATE TABLE EMPLOYEE (? ? ? ? FIRST_NAME? CHAR(20) NOT NULL, LAST_NAME? CHAR(20),? ? ? ? AGE INT,? ? ? ? ? SEX CHAR(1),? ? ? ? INCOME FLOAT )"""cursor.execute(sql)# 關(guān)閉數(shù)據(jù)庫連接db.close()數(shù)據(jù)庫插入操作以下實(shí)例使用執(zhí)行 SQL INSERT 語句向表 EMPLOYEE 插入記錄:#!/usr/bin/python# -*- coding: UTF-8 -*-import MySQLdb# 打開數(shù)據(jù)庫連接db = MySQLdb.connect("localhost","testuser","test123","TESTDB" )# 使用cursor()方法獲取操作游標(biāo) cursor = db.cursor()# SQL 插入語句sql = """INSERT INTO EMPLOYEE(FIRST_NAME,? ? ? ? LAST_NAME, AGE, SEX, INCOME)? ? ? ? VALUES ('Mac', 'Mohan', 20, 'M', 2000)"""try:? # 執(zhí)行sql語句? cursor.execute(sql)? # 提交到數(shù)據(jù)庫執(zhí)行? db.commit()except:? # Rollback in case there is any error? db.rollback()# 關(guān)閉數(shù)據(jù)庫連接db.close()以上例子也可以寫成如下形式:#!/usr/bin/python# -*- coding: UTF-8 -*-import MySQLdb# 打開數(shù)據(jù)庫連接db = MySQLdb.connect("localhost","testuser","test123","TESTDB" )# 使用cursor()方法獲取操作游標(biāo) cursor = db.cursor()# SQL 插入語句sql = "INSERT INTO EMPLOYEE(FIRST_NAME, \? ? ? LAST_NAME, AGE, SEX, INCOME) \? ? ? VALUES ('%s', '%s', '%d', '%c', '%d' )" % \? ? ? ('Mac', 'Mohan', 20, 'M', 2000)try:? # 執(zhí)行sql語句? cursor.execute(sql)? # 提交到數(shù)據(jù)庫執(zhí)行? db.commit()except:? # 發(fā)生錯(cuò)誤時(shí)回滾? db.rollback()# 關(guān)閉數(shù)據(jù)庫連接db.close()實(shí)例:以下代碼使用變量向SQL語句中傳遞參數(shù):..................................user_id = "test123"password = "password"con.execute('insert into Login values("%s", "%s")' % \? ? ? ? ? ? (user_id, password))..................................數(shù)據(jù)庫查詢操作Python查詢Mysql使用 fetchone() 方法獲取單條數(shù)據(jù), 使用fetchall() 方法獲取多條數(shù)據(jù)涌哲。fetchone(): 該方法獲取下一個(gè)查詢結(jié)果集胖缤。結(jié)果集是一個(gè)對象fetchall():接收全部的返回結(jié)果行.rowcount: 這是一個(gè)只讀屬性,并返回執(zhí)行execute()方法后影響的行數(shù)阀圾。實(shí)例:查詢EMPLOYEE表中salary(工資)字段大于1000的所有數(shù)據(jù):#!/usr/bin/python# -*- coding: UTF-8 -*-import MySQLdb# 打開數(shù)據(jù)庫連接db = MySQLdb.connect("localhost","testuser","test123","TESTDB" )# 使用cursor()方法獲取操作游標(biāo) cursor = db.cursor()# SQL 查詢語句sql = "SELECT * FROM EMPLOYEE \? ? ? WHERE INCOME > '%d'" % (1000)try:? # 執(zhí)行SQL語句? cursor.execute(sql)? # 獲取所有記錄列表? results = cursor.fetchall()? for row in results:? ? ? fname = row[0]? ? ? lname = row[1]? ? ? age = row[2]? ? ? sex = row[3]? ? ? income = row[4]? ? ? # 打印結(jié)果? ? ? print "fname=%s,lname=%s,age=%d,sex=%s,income=%d" % \? ? ? ? ? ? (fname, lname, age, sex, income )except:? print "Error: unable to fecth data"# 關(guān)閉數(shù)據(jù)庫連接db.close()以上腳本執(zhí)行結(jié)果如下:fname=Mac, lname=Mohan, age=20, sex=M, income=2000數(shù)據(jù)庫更新操作更新操作用于更新數(shù)據(jù)表的的數(shù)據(jù)草姻,以下實(shí)例將 EMPLOYEE 表中的 SEX 字段為 'M' 的 AGE 字段遞增 1:#!/usr/bin/python# -*- coding: UTF-8 -*-import MySQLdb# 打開數(shù)據(jù)庫連接db = MySQLdb.connect("localhost","testuser","test123","TESTDB" )# 使用cursor()方法獲取操作游標(biāo) cursor = db.cursor()# SQL 更新語句sql = "UPDATE EMPLOYEE SET AGE = AGE + 1 WHERE SEX = '%c'" % ('M')try:? # 執(zhí)行SQL語句? cursor.execute(sql)? # 提交到數(shù)據(jù)庫執(zhí)行? db.commit()except:? # 發(fā)生錯(cuò)誤時(shí)回滾 db.rollback()# 關(guān)閉數(shù)據(jù)庫連接db.close()刪除操作刪除操作用于刪除數(shù)據(jù)表中的數(shù)據(jù),以下實(shí)例演示了刪除數(shù)據(jù)表 EMPLOYEE 中 AGE 大于 20 的所有數(shù)據(jù):#!/usr/bin/python# -*- coding: UTF-8 -*-import MySQLdb# 打開數(shù)據(jù)庫連接db = MySQLdb.connect("localhost","testuser","test123","TESTDB" )# 使用cursor()方法獲取操作游標(biāo) cursor = db.cursor()# SQL 刪除語句sql = "DELETE FROM EMPLOYEE WHERE AGE > '%d'" % (20)try:? # 執(zhí)行SQL語句? cursor.execute(sql)? # 提交修改? db.commit()except:? # 發(fā)生錯(cuò)誤時(shí)回滾? db.rollback()# 關(guān)閉連接db.close()執(zhí)行事務(wù)事務(wù)機(jī)制可以確保數(shù)據(jù)一致性稍刀。事務(wù)應(yīng)該具有4個(gè)屬性:原子性撩独、一致性、隔離性账月、持久性综膀。這四個(gè)屬性通常稱為ACID特性。原子性(atomicity)局齿。一個(gè)事務(wù)是一個(gè)不可分割的工作單位剧劝,事務(wù)中包括的諸操作要么都做,要么都不做抓歼。一致性(consistency)讥此。事務(wù)必須是使數(shù)據(jù)庫從一個(gè)一致性狀態(tài)變到另一個(gè)一致性狀態(tài)。一致性與原子性是密切相關(guān)的谣妻。隔離性(isolation)萄喳。一個(gè)事務(wù)的執(zhí)行不能被其他事務(wù)干擾。即一個(gè)事務(wù)內(nèi)部的操作及使用的數(shù)據(jù)對并發(fā)的其他事務(wù)是隔離的蹋半,并發(fā)執(zhí)行的各個(gè)事務(wù)之間不能互相干擾他巨。持久性(durability)。持續(xù)性也稱永久性(permanence)减江,指一個(gè)事務(wù)一旦提交染突,它對數(shù)據(jù)庫中數(shù)據(jù)的改變就應(yīng)該是永久性的。接下來的其他操作或故障不應(yīng)該對其有任何影響辈灼。Python DB API 2.0 的事務(wù)提供了兩個(gè)方法 commit 或 rollback份企。實(shí)例:# SQL刪除記錄語句sql = "DELETE FROM EMPLOYEE WHERE AGE > '%d'" % (20)try:? # 執(zhí)行SQL語句? cursor.execute(sql)? # 向數(shù)據(jù)庫提交? db.commit()except:? # 發(fā)生錯(cuò)誤時(shí)回滾? db.rollback()對于支持事務(wù)的數(shù)據(jù)庫, 在Python數(shù)據(jù)庫編程中巡莹,當(dāng)游標(biāo)建立之時(shí)司志,就自動(dòng)開始了一個(gè)隱形的數(shù)據(jù)庫事務(wù)。commit()方法游標(biāo)的所有更新操作榕莺,rollback()方法回滾當(dāng)前游標(biāo)的所有操作俐芯。每一個(gè)方法都開始了一個(gè)新的事務(wù)。錯(cuò)誤處理DB API中定義了一些數(shù)據(jù)庫操作的錯(cuò)誤及異常钉鸯,下表列出了這些錯(cuò)誤和異常:Python 網(wǎng)絡(luò)編程Python 提供了兩個(gè)級別訪問的網(wǎng)絡(luò)服務(wù)。:低級別的網(wǎng)絡(luò)服務(wù)支持基本的 Socket邮辽,它提供了標(biāo)準(zhǔn)的 BSD Sockets API唠雕,可以訪問底層操作系統(tǒng)Socket接口的全部方法贸营。高級別的網(wǎng)絡(luò)服務(wù)模塊 SocketServer, 它提供了服務(wù)器中心類岩睁,可以簡化網(wǎng)絡(luò)服務(wù)器的開發(fā)钞脂。什么是 Socket?Socket又稱"套接字",應(yīng)用程序通常通過"套接字"向網(wǎng)絡(luò)發(fā)出請求或者應(yīng)答網(wǎng)絡(luò)請求捕儒,使主機(jī)間或者一臺計(jì)算機(jī)上的進(jìn)程間可以通訊冰啃。socket()函數(shù)Python 中,我們用 socket()函數(shù)來創(chuàng)建套接字刘莹,語法格式如下:socket.socket([family[, type[, proto]]])參數(shù)family: 套接字家族可以使AF_UNIX或者AF_INETtype: 套接字類型可以根據(jù)是面向連接的還是非連接分為SOCK_STREAM或SOCK_DGRAMprotocol: 一般不填默認(rèn)為0.Socket 對象(內(nèi)建)方法簡單實(shí)例服務(wù)端我們使用 socket 模塊的 socket 函數(shù)來創(chuàng)建一個(gè) socket 對象阎毅。socket 對象可以通過調(diào)用其他函數(shù)來設(shè)置一個(gè) socket 服務(wù)。現(xiàn)在我們可以通過調(diào)用 bind(hostname, port) 函數(shù)來指定服務(wù)的 port(端口)点弯。接著扇调,我們調(diào)用 socket 對象的 accept 方法。該方法等待客戶端的連接抢肛,并返回 connection 對象狼钮,表示已連接到客戶端。完整代碼如下:#!/usr/bin/python# -*- coding: UTF-8 -*-# 文件名:server.pyimport socket? ? ? ? ? ? ? # 導(dǎo)入 socket 模塊s = socket.socket()? ? ? ? # 創(chuàng)建 socket 對象host = socket.gethostname() # 獲取本地主機(jī)名port = 12345? ? ? ? ? ? ? ? # 設(shè)置端口s.bind((host, port))? ? ? ? # 綁定端口s.listen(5)? ? ? ? ? ? ? ? # 等待客戶端連接while True:? ? c, addr = s.accept()? ? # 建立客戶端連接捡絮。? ? print '連接地址:', addr? ? c.send('歡迎訪問菜鳥教程熬芜!')? ? c.close()? ? ? ? ? ? ? ? # 關(guān)閉連接客戶端接下來我們寫一個(gè)簡單的客戶端實(shí)例連接到以上創(chuàng)建的服務(wù)。端口號為 12345福稳。socket.connect(hosname, port ) 方法打開一個(gè) TCP 連接到主機(jī)為 hostname 端口為 port 的服務(wù)商猛蔽。連接后我們就可以從服務(wù)端后期數(shù)據(jù),記住灵寺,操作完成后需要關(guān)閉連接曼库。完整代碼如下:#!/usr/bin/python# -*- coding: UTF-8 -*-# 文件名:client.pyimport socket? ? ? ? ? ? ? # 導(dǎo)入 socket 模塊s = socket.socket()? ? ? ? # 創(chuàng)建 socket 對象host = socket.gethostname() # 獲取本地主機(jī)名port = 12345? ? ? ? ? ? ? ? # 設(shè)置端口好s.connect((host, port))print s.recv(1024)s.close()? 現(xiàn)在我們打開兩個(gè)終端,第一個(gè)終端執(zhí)行 server.py 文件:$ python server.py第二個(gè)終端執(zhí)行 client.py 文件:$ python client.py 歡迎訪問菜鳥教程略板!這是我們再打開第一個(gè)終端毁枯,就會看到有以下信息輸出:連接地址: ('192.168.0.118', 62461)Python Internet 模塊以下列出了 Python 網(wǎng)絡(luò)編程的一些重要模塊:更多內(nèi)容可以參閱官網(wǎng)的 Python Socket Library and Modules。Python SMTP發(fā)送郵件SMTP(Simple Mail Transfer Protocol)即簡單郵件傳輸協(xié)議,它是一組用于由源地址到目的地址傳送郵件的規(guī)則叮称,由它來控制信件的中轉(zhuǎn)方式艇挨。python的smtplib提供了一種很方便的途徑發(fā)送電子郵件。它對smtp協(xié)議進(jìn)行了簡單的封裝蹭沛。Python創(chuàng)建 SMTP 對象語法如下:import smtplibsmtpObj = smtplib.SMTP( [host [, port [, local_hostname]]] )參數(shù)說明:host: SMTP 服務(wù)器主機(jī)排截。 你可以指定主機(jī)的ip地址或者域名如: runoob.com,這個(gè)是可選參數(shù)挠蛉。port: 如果你提供了 host 參數(shù), 你需要指定 SMTP 服務(wù)使用的端口號祭示,一般情況下 SMTP 端口號為25。local_hostname: 如果 SMTP 在你的本機(jī)上谴古,你只需要指定服務(wù)器地址為 localhost 即可质涛。Python SMTP 對象使用 sendmail 方法發(fā)送郵件稠歉,語法如下:SMTP.sendmail(from_addr, to_addrs, msg[, mail_options, rcpt_options]參數(shù)說明:from_addr: 郵件發(fā)送者地址。to_addrs: 字符串列表汇陆,郵件發(fā)送地址怒炸。msg: 發(fā)送消息這里要注意一下第三個(gè)參數(shù),msg 是字符串毡代,表示郵件阅羹。我們知道郵件一般由標(biāo)題,發(fā)信人教寂,收件人捏鱼,郵件內(nèi)容,附件等構(gòu)成孝宗,發(fā)送郵件的時(shí)候穷躁,要注意 msg 的格式。這個(gè)格式就是 smtp 協(xié)議中定義的格式因妇。實(shí)例以下執(zhí)行實(shí)例需要你本機(jī)已安裝了支持 SMTP 的服務(wù)问潭,如:sendmail。以下是一個(gè)使用 Python 發(fā)送郵件簡單的實(shí)例:實(shí)例#!/usr/bin/python# -*- coding: UTF-8 -*- import smtplibfrom email.mime.text import MIMETextfrom email.header import Header sender = 'from@runoob.com'receivers = ['429240967@qq.com']? # 接收郵件婚被,可設(shè)置為你的QQ郵箱或者其他郵箱 # 三個(gè)參數(shù):第一個(gè)為文本內(nèi)容狡忙,第二個(gè) plain 設(shè)置文本格式,第三個(gè) utf-8 設(shè)置編碼message = MIMEText('Python 郵件發(fā)送測試...', 'plain', 'utf-8')message['From'] = Header("菜鳥教程", 'utf-8')message['To'] =? Header("測試", 'utf-8') subject = 'Python SMTP 郵件測試'message['Subject'] = Header(subject, 'utf-8')? try:? ? smtpObj = smtplib.SMTP('localhost')? ? smtpObj.sendmail(sender, receivers, message.as_string())? ? print "郵件發(fā)送成功"except smtplib.SMTPException:? ? print "Error: 無法發(fā)送郵件"我們使用三個(gè)引號來設(shè)置郵件信息址芯,標(biāo)準(zhǔn)郵件需要三個(gè)頭部信息: From, To, 和 Subject 灾茁,每個(gè)信息直接使用空行分割。我們通過實(shí)例化 smtplib 模塊的 SMTP 對象 smtpObj 來連接到 SMTP 訪問谷炸,并使用 sendmail 方法來發(fā)送信息北专。執(zhí)行以上程序,如果你本機(jī)安裝 sendmail(郵件傳輸代理程序)旬陡,就會輸出:$ python test.py 郵件發(fā)送成功查看我們的收件箱(一般在垃圾箱)拓颓,就可以查看到郵件信息:如果我們本機(jī)沒有 sendmail 訪問,也可以使用其他郵件服務(wù)商的 SMTP 訪問(QQ描孟、網(wǎng)易驶睦、Google等)。實(shí)例#!/usr/bin/python# -*- coding: UTF-8 -*- import smtplibfrom email.mime.text import MIMETextfrom email.header import Header # 第三方 SMTP 服務(wù)mail_host="smtp.XXX.com"? #設(shè)置服務(wù)器mail_user="XXXX"? ? #用戶名mail_pass="XXXXXX"? #口令? sender = 'from@runoob.com'receivers = ['429240967@qq.com']? # 接收郵件匿醒,可設(shè)置為你的QQ郵箱或者其他郵箱 message = MIMEText('Python 郵件發(fā)送測試...', 'plain', 'utf-8')message['From'] = Header("菜鳥教程", 'utf-8')message['To'] =? Header("測試", 'utf-8') subject = 'Python SMTP 郵件測試'message['Subject'] = Header(subject, 'utf-8')? try:? ? smtpObj = smtplib.SMTP()? ? smtpObj.connect(mail_host, 25)? ? # 25 為 SMTP 端口號? ? smtpObj.login(mail_user,mail_pass)? ? ? smtpObj.sendmail(sender, receivers, message.as_string())? ? print "郵件發(fā)送成功"except smtplib.SMTPException:? ? print "Error: 無法發(fā)送郵件"使用Python發(fā)送HTML格式的郵件Python發(fā)送HTML格式的郵件與發(fā)送純文本消息的郵件不同之處就是將MIMEText中_subtype設(shè)置為html场航。具體代碼如下:實(shí)例#!/usr/bin/python# -*- coding: UTF-8 -*- import smtplibfrom email.mime.text import MIMETextfrom email.header import Header sender = 'from@runoob.com'receivers = ['429240967@qq.com']? # 接收郵件,可設(shè)置為你的QQ郵箱或者其他郵箱 mail_msg = """
Python 郵件發(fā)送測試...
這是一個(gè)鏈接
"""message = MIMEText(mail_msg, 'html', 'utf-8')message['From'] = Header("菜鳥教程", 'utf-8')message['To'] =? Header("測試", 'utf-8') subject = 'Python SMTP 郵件測試'message['Subject'] = Header(subject, 'utf-8')? try:? ? smtpObj = smtplib.SMTP('localhost')? ? smtpObj.sendmail(sender, receivers, message.as_string())? ? print "郵件發(fā)送成功"except smtplib.SMTPException:? ? print "Error: 無法發(fā)送郵件"執(zhí)行以上程序廉羔,如果你本機(jī)安裝sendmail溉痢,就會輸出:$ python test.py 郵件發(fā)送成功查看我們的收件箱(一般在垃圾箱),就可以查看到郵件信息:Python 發(fā)送帶附件的郵件發(fā)送帶附件的郵件,首先要?jiǎng)?chuàng)建MIMEMultipart()實(shí)例适室,然后構(gòu)造附件嫡意,如果有多個(gè)附件举瑰,可依次構(gòu)造捣辆,最后利用smtplib.smtp發(fā)送。實(shí)例#!/usr/bin/python# -*- coding: UTF-8 -*- import smtplibfrom email.mime.text import MIMETextfrom email.mime.multipart import MIMEMultipartfrom email.header import Header sender = 'from@runoob.com'receivers = ['429240967@qq.com']? # 接收郵件此迅,可設(shè)置為你的QQ郵箱或者其他郵箱 #創(chuàng)建一個(gè)帶附件的實(shí)例message = MIMEMultipart()message['From'] = Header("菜鳥教程", 'utf-8')message['To'] =? Header("測試", 'utf-8')subject = 'Python SMTP 郵件測試'message['Subject'] = Header(subject, 'utf-8') #郵件正文內(nèi)容message.attach(MIMEText('這是菜鳥教程Python 郵件發(fā)送測試……', 'plain', 'utf-8')) # 構(gòu)造附件1汽畴,傳送當(dāng)前目錄下的 test.txt 文件att1 = MIMEText(open('test.txt', 'rb').read(), 'base64', 'utf-8')att1["Content-Type"] = 'application/octet-stream'# 這里的filename可以任意寫,寫什么名字耸序,郵件中顯示什么名字att1["Content-Disposition"] = 'attachment; filename="test.txt"'message.attach(att1) # 構(gòu)造附件2忍些,傳送當(dāng)前目錄下的 runoob.txt 文件att2 = MIMEText(open('runoob.txt', 'rb').read(), 'base64', 'utf-8')att2["Content-Type"] = 'application/octet-stream'att2["Content-Disposition"] = 'attachment; filename="runoob.txt"'message.attach(att2) try:? ? smtpObj = smtplib.SMTP('localhost')? ? smtpObj.sendmail(sender, receivers, message.as_string())? ? print "郵件發(fā)送成功"except smtplib.SMTPException:? ? print "Error: 無法發(fā)送郵件"$ python test.py 郵件發(fā)送成功查看我們的收件箱(一般在垃圾箱),就可以查看到郵件信息:在 HTML 文本中添加圖片郵件的 HTML 文本中一般郵件服務(wù)商添加外鏈?zhǔn)菬o效的坎怪,正確添加突破的實(shí)例如下所示:實(shí)例#!/usr/bin/python# -*- coding: UTF-8 -*- import smtplibfrom email.mime.image import MIMEImagefrom email.mime.multipart import MIMEMultipartfrom email.mime.text import MIMETextfrom email.header import Header sender = 'from@runoob.com'receivers = ['429240967@qq.com']? # 接收郵件罢坝,可設(shè)置為你的QQ郵箱或者其他郵箱 msgRoot = MIMEMultipart('related')msgRoot['From'] = Header("菜鳥教程", 'utf-8')msgRoot['To'] =? Header("測試", 'utf-8')subject = 'Python SMTP 郵件測試'msgRoot['Subject'] = Header(subject, 'utf-8') msgAlternative = MIMEMultipart('alternative')msgRoot.attach(msgAlternative)? mail_msg = """
Python 郵件發(fā)送測試...
菜鳥教程鏈接
圖片演示:
不支持該協(xié)議 取消 重新上傳
不支持該協(xié)議取消重新上傳
"""msgAlternative.attach(MIMEText(mail_msg, 'html', 'utf-8')) # 指定圖片為當(dāng)前目錄fp = open('test.png', 'rb')msgImage = MIMEImage(fp.read())fp.close() # 定義圖片 ID,在 HTML 文本中引用msgImage.add_header('Content-ID', '')msgRoot.attach(msgImage) try:? ? smtpObj = smtplib.SMTP('localhost')? ? smtpObj.sendmail(sender, receivers, msgRoot.as_string())? ? print "郵件發(fā)送成功"except smtplib.SMTPException:? ? print "Error: 無法發(fā)送郵件"$ python test.py 郵件發(fā)送成功查看我們的收件箱(如果在垃圾箱可能需要移動(dòng)到收件箱才可正常顯示)搅窿,就可以查看到郵件信息:使用第三方 SMTP 服務(wù)發(fā)送這里使用了 QQ 郵箱(你也可以使用 163嘁酿,Gmail等)的 SMTP 服務(wù),需要做以下配置:QQ 郵箱通過生成授權(quán)碼來設(shè)置密碼:QQ 郵箱 SMTP 服務(wù)器地址:smtp.qq.com男应,ssl 端口:465闹司。以下實(shí)例你需要修改:發(fā)件人郵箱(你的QQ郵箱),密碼沐飘,收件人郵箱(可發(fā)給自己)游桩。QQ SMTP#!/usr/bin/python# -*- coding: UTF-8 -*- import smtplibfrom email.mime.text import MIMETextfrom email.utils import formataddr my_sender='429240967@qq.com'? ? # 發(fā)件人郵箱賬號my_pass = 'xxxxxxxxxx'? ? ? ? ? ? ? # 發(fā)件人郵箱密碼my_user='429240967@qq.com'? ? ? # 收件人郵箱賬號,我這邊發(fā)送給自己def mail():? ? ret=True? ? try:? ? ? ? msg=MIMEText('填寫郵件內(nèi)容','plain','utf-8')? ? ? ? msg['From']=formataddr(["FromRunoob",my_sender])? # 括號里的對應(yīng)發(fā)件人郵箱昵稱耐朴、發(fā)件人郵箱賬號? ? ? ? msg['To']=formataddr(["FK",my_user])? ? ? ? ? ? ? # 括號里的對應(yīng)收件人郵箱昵稱借卧、收件人郵箱賬號? ? ? ? msg['Subject']="菜鳥教程發(fā)送郵件測試"? ? ? ? ? ? ? ? # 郵件的主題,也可以說是標(biāo)題? ? ? ? server=smtplib.SMTP_SSL("smtp.qq.com", 465)? # 發(fā)件人郵箱中的SMTP服務(wù)器筛峭,端口是25? ? ? ? server.login(my_sender, my_pass)? # 括號中對應(yīng)的是發(fā)件人郵箱賬號铐刘、郵箱密碼? ? ? ? server.sendmail(my_sender,[my_user,],msg.as_string())? # 括號中對應(yīng)的是發(fā)件人郵箱賬號、收件人郵箱賬號蜒滩、發(fā)送郵件? ? ? ? server.quit()? # 關(guān)閉連接? ? except Exception:? # 如果 try 中的語句沒有執(zhí)行滨达,則會執(zhí)行下面的 ret=False? ? ? ? ret=False? ? return ret ret=mail()if ret:? ? print("郵件發(fā)送成功")else:? ? print("郵件發(fā)送失敗")$ python test.py 郵件發(fā)送成功發(fā)送成功后,登陸收件人郵箱即可查看:更多內(nèi)容請參閱:https://docs.python.org/2/library/email-examples.html俯艰。Python 多線程多線程類似于同時(shí)執(zhí)行多個(gè)不同程序捡遍,多線程運(yùn)行有如下優(yōu)點(diǎn):使用線程可以把占據(jù)長時(shí)間的程序中的任務(wù)放到后臺去處理。用戶界面可以更加吸引人竹握,這樣比如用戶點(diǎn)擊了一個(gè)按鈕去觸發(fā)某些事件的處理画株,可以彈出一個(gè)進(jìn)度條來顯示處理的進(jìn)度程序的運(yùn)行速度可能加快在一些等待的任務(wù)實(shí)現(xiàn)上如用戶輸入、文件讀寫和網(wǎng)絡(luò)收發(fā)數(shù)據(jù)等,線程就比較有用了谓传。在這種情況下我們可以釋放一些珍貴的資源如內(nèi)存占用等等蜈项。線程在執(zhí)行過程中與進(jìn)程還是有區(qū)別的。每個(gè)獨(dú)立的線程有一個(gè)程序運(yùn)行的入口续挟、順序執(zhí)行序列和程序的出口紧卒。但是線程不能夠獨(dú)立執(zhí)行,必須依存在應(yīng)用程序中诗祸,由應(yīng)用程序提供多個(gè)線程執(zhí)行控制跑芳。每個(gè)線程都有他自己的一組CPU寄存器,稱為線程的上下文直颅,該上下文反映了線程上次運(yùn)行該線程的CPU寄存器的狀態(tài)博个。指令指針和堆棧指針寄存器是線程上下文中兩個(gè)最重要的寄存器,線程總是在進(jìn)程得到上下文中運(yùn)行的功偿,這些地址都用于標(biāo)志擁有線程的進(jìn)程地址空間中的內(nèi)存盆佣。線程可以被搶占(中斷)。在其他線程正在運(yùn)行時(shí)械荷,線程可以暫時(shí)擱置(也稱為睡眠) -- 這就是線程的退讓共耍。開始學(xué)習(xí)Python線程Python中使用線程有兩種方式:函數(shù)或者用類來包裝線程對象。函數(shù)式:調(diào)用thread模塊中的start_new_thread()函數(shù)來產(chǎn)生新線程养葵。語法如下:thread.start_new_thread ( function, args[, kwargs] )參數(shù)說明:function - 線程函數(shù)征堪。args - 傳遞給線程函數(shù)的參數(shù),他必須是個(gè)tuple類型。kwargs - 可選參數(shù)关拒。實(shí)例(Python 2.0+)#!/usr/bin/python# -*- coding: UTF-8 -*- import threadimport time # 為線程定義一個(gè)函數(shù)def print_time( threadName, delay):? count = 0? while count < 5:? ? ? time.sleep(delay)? ? ? count += 1? ? ? print "%s: %s" % ( threadName, time.ctime(time.time()) ) # 創(chuàng)建兩個(gè)線程try:? thread.start_new_thread( print_time, ("Thread-1", 2, ) )? thread.start_new_thread( print_time, ("Thread-2", 4, ) )except:? print "Error: unable to start thread" while 1:? pass執(zhí)行以上程序輸出結(jié)果如下:Thread-1: Thu Jan 22 15:42:17 2009Thread-1: Thu Jan 22 15:42:19 2009Thread-2: Thu Jan 22 15:42:19 2009Thread-1: Thu Jan 22 15:42:21 2009Thread-2: Thu Jan 22 15:42:23 2009Thread-1: Thu Jan 22 15:42:23 2009Thread-1: Thu Jan 22 15:42:25 2009Thread-2: Thu Jan 22 15:42:27 2009Thread-2: Thu Jan 22 15:42:31 2009Thread-2: Thu Jan 22 15:42:35 2009線程的結(jié)束一般依靠線程函數(shù)的自然結(jié)束佃蚜;也可以在線程函數(shù)中調(diào)用thread.exit(),他拋出SystemExit exception着绊,達(dá)到退出線程的目的谐算。線程模塊Python通過兩個(gè)標(biāo)準(zhǔn)庫thread和threading提供對線程的支持。thread提供了低級別的归露、原始的線程以及一個(gè)簡單的鎖洲脂。thread 模塊提供的其他方法:threading.currentThread(): 返回當(dāng)前的線程變量。threading.enumerate(): 返回一個(gè)包含正在運(yùn)行的線程的list剧包。正在運(yùn)行指線程啟動(dòng)后恐锦、結(jié)束前,不包括啟動(dòng)前和終止后的線程疆液。threading.activeCount(): 返回正在運(yùn)行的線程數(shù)量一铅,與len(threading.enumerate())有相同的結(jié)果。除了使用方法外堕油,線程模塊同樣提供了Thread類來處理線程潘飘,Thread類提供了以下方法:run(): 用以表示線程活動(dòng)的方法肮之。start():啟動(dòng)線程活動(dòng)。join([time]): 等待至線程中止卜录。這阻塞調(diào)用線程直至線程的join() 方法被調(diào)用中止-正常退出或者拋出未處理的異常-或者是可選的超時(shí)發(fā)生戈擒。isAlive(): 返回線程是否活動(dòng)的。getName(): 返回線程名艰毒。setName(): 設(shè)置線程名筐高。使用Threading模塊創(chuàng)建線程使用Threading模塊創(chuàng)建線程,直接從threading.Thread繼承现喳,然后重寫__init__方法和run方法:實(shí)例(Python 2.0+)#!/usr/bin/python# -*- coding: UTF-8 -*- import threadingimport time exitFlag = 0 class myThread (threading.Thread):? #繼承父類threading.Thread? ? def __init__(self, threadID, name, counter):? ? ? ? threading.Thread.__init__(self)? ? ? ? self.threadID = threadID? ? ? ? self.name = name? ? ? ? self.counter = counter? ? def run(self):? ? ? ? ? ? ? ? ? #把要執(zhí)行的代碼寫到run函數(shù)里面 線程在創(chuàng)建后會直接運(yùn)行run函數(shù)? ? ? ? print "Starting " + self.name? ? ? ? print_time(self.name, self.counter, 5)? ? ? ? print "Exiting " + self.name def print_time(threadName, delay, counter):? ? while counter:? ? ? ? if exitFlag:? ? ? ? ? ? threading.Thread.exit()? ? ? ? time.sleep(delay)? ? ? ? print "%s: %s" % (threadName, time.ctime(time.time()))? ? ? ? counter -= 1 # 創(chuàng)建新線程thread1 = myThread(1, "Thread-1", 1)thread2 = myThread(2, "Thread-2", 2) # 開啟線程thread1.start()thread2.start() print "Exiting Main Thread"以上程序執(zhí)行結(jié)果如下凯傲;Starting Thread-1Starting Thread-2Exiting Main ThreadThread-1: Thu Mar 21 09:10:03 2013Thread-1: Thu Mar 21 09:10:04 2013Thread-2: Thu Mar 21 09:10:04 2013Thread-1: Thu Mar 21 09:10:05 2013Thread-1: Thu Mar 21 09:10:06 2013Thread-2: Thu Mar 21 09:10:06 2013Thread-1: Thu Mar 21 09:10:07 2013Exiting Thread-1Thread-2: Thu Mar 21 09:10:08 2013Thread-2: Thu Mar 21 09:10:10 2013Thread-2: Thu Mar 21 09:10:12 2013Exiting Thread-2線程同步如果多個(gè)線程共同對某個(gè)數(shù)據(jù)修改犬辰,則可能出現(xiàn)不可預(yù)料的結(jié)果嗦篱,為了保證數(shù)據(jù)的正確性,需要對多個(gè)線程進(jìn)行同步幌缝。使用Thread對象的Lock和Rlock可以實(shí)現(xiàn)簡單的線程同步灸促,這兩個(gè)對象都有acquire方法和release方法,對于那些需要每次只允許一個(gè)線程操作的數(shù)據(jù)涵卵,可以將其操作放到acquire和release方法之間浴栽。如下:多線程的優(yōu)勢在于可以同時(shí)運(yùn)行多個(gè)任務(wù)(至少感覺起來是這樣)。但是當(dāng)線程需要共享數(shù)據(jù)時(shí)轿偎,可能存在數(shù)據(jù)不同步的問題典鸡。考慮這樣一種情況:一個(gè)列表里所有元素都是0坏晦,線程"set"從后向前把所有元素改成1萝玷,而線程"print"負(fù)責(zé)從前往后讀取列表并打印。那么昆婿,可能線程"set"開始改的時(shí)候球碉,線程"print"便來打印列表了,輸出就成了一半0一半1仓蛆,這就是數(shù)據(jù)的不同步睁冬。為了避免這種情況,引入了鎖的概念看疙。鎖有兩種狀態(tài)——鎖定和未鎖定豆拨。每當(dāng)一個(gè)線程比如"set"要訪問共享數(shù)據(jù)時(shí),必須先獲得鎖定能庆;如果已經(jīng)有別的線程比如"print"獲得鎖定了施禾,那么就讓線程"set"暫停,也就是同步阻塞相味;等到線程"print"訪問完畢拾积,釋放鎖以后殉挽,再讓線程"set"繼續(xù)。經(jīng)過這樣的處理拓巧,打印列表時(shí)要么全部輸出0斯碌,要么全部輸出1,不會再出現(xiàn)一半0一半1的尷尬場面肛度。實(shí)例(Python 2.0+)#!/usr/bin/python# -*- coding: UTF-8 -*- import threadingimport time class myThread (threading.Thread):? ? def __init__(self, threadID, name, counter):? ? ? ? threading.Thread.__init__(self)? ? ? ? self.threadID = threadID? ? ? ? self.name = name? ? ? ? self.counter = counter? ? def run(self):? ? ? ? print "Starting " + self.name? ? ? # 獲得鎖傻唾,成功獲得鎖定后返回True? ? ? # 可選的timeout參數(shù)不填時(shí)將一直阻塞直到獲得鎖定? ? ? # 否則超時(shí)后將返回False? ? ? ? threadLock.acquire()? ? ? ? print_time(self.name, self.counter, 3)? ? ? ? # 釋放鎖? ? ? ? threadLock.release() def print_time(threadName, delay, counter):? ? while counter:? ? ? ? time.sleep(delay)? ? ? ? print "%s: %s" % (threadName, time.ctime(time.time()))? ? ? ? counter -= 1 threadLock = threading.Lock()threads = [] # 創(chuàng)建新線程thread1 = myThread(1, "Thread-1", 1)thread2 = myThread(2, "Thread-2", 2) # 開啟新線程thread1.start()thread2.start() # 添加線程到線程列表threads.append(thread1)threads.append(thread2) # 等待所有線程完成for t in threads:? ? t.join()print "Exiting Main Thread"線程優(yōu)先級隊(duì)列( Queue)Python的Queue模塊中提供了同步的、線程安全的隊(duì)列類承耿,包括FIFO(先入先出)隊(duì)列Queue冠骄,LIFO(后入先出)隊(duì)列LifoQueue,和優(yōu)先級隊(duì)列PriorityQueue加袋。這些隊(duì)列都實(shí)現(xiàn)了鎖原語凛辣,能夠在多線程中直接使用≈吧眨可以使用隊(duì)列來實(shí)現(xiàn)線程間的同步扁誓。Queue模塊中的常用方法:Queue.qsize() 返回隊(duì)列的大小Queue.empty() 如果隊(duì)列為空,返回True,反之FalseQueue.full() 如果隊(duì)列滿了蚀之,返回True,反之FalseQueue.full 與 maxsize 大小對應(yīng)Queue.get([block[, timeout]])獲取隊(duì)列蝗敢,timeout等待時(shí)間Queue.get_nowait() 相當(dāng)Queue.get(False)Queue.put(item) 寫入隊(duì)列,timeout等待時(shí)間Queue.put_nowait(item) 相當(dāng)Queue.put(item, False)Queue.task_done() 在完成一項(xiàng)工作之后足删,Queue.task_done()函數(shù)向任務(wù)已經(jīng)完成的隊(duì)列發(fā)送一個(gè)信號Queue.join() 實(shí)際上意味著等到隊(duì)列為空寿谴,再執(zhí)行別的操作實(shí)例(Python 2.0+)#!/usr/bin/python# -*- coding: UTF-8 -*- import Queueimport threadingimport time exitFlag = 0 class myThread (threading.Thread):? ? def __init__(self, threadID, name, q):? ? ? ? threading.Thread.__init__(self)? ? ? ? self.threadID = threadID? ? ? ? self.name = name? ? ? ? self.q = q? ? def run(self):? ? ? ? print "Starting " + self.name? ? ? ? process_data(self.name, self.q)? ? ? ? print "Exiting " + self.name def process_data(threadName, q):? ? while not exitFlag:? ? ? ? queueLock.acquire()? ? ? ? if not workQueue.empty():? ? ? ? ? ? data = q.get()? ? ? ? ? ? queueLock.release()? ? ? ? ? ? print "%s processing %s" % (threadName, data)? ? ? ? else:? ? ? ? ? ? queueLock.release()? ? ? ? time.sleep(1) threadList = ["Thread-1", "Thread-2", "Thread-3"]nameList = ["One", "Two", "Three", "Four", "Five"]queueLock = threading.Lock()workQueue = Queue.Queue(10)threads = []threadID = 1 # 創(chuàng)建新線程for tName in threadList:? ? thread = myThread(threadID, tName, workQueue)? ? thread.start()? ? threads.append(thread)? ? threadID += 1 # 填充隊(duì)列queueLock.acquire()for word in nameList:? ? workQueue.put(word)queueLock.release() # 等待隊(duì)列清空while not workQueue.empty():? ? pass # 通知線程是時(shí)候退出exitFlag = 1 # 等待所有線程完成for t in threads:? ? t.join()print "Exiting Main Thread"以上程序執(zhí)行結(jié)果:Starting Thread-1Starting Thread-2Starting Thread-3Thread-1 processing OneThread-2 processing TwoThread-3 processing ThreeThread-1 processing FourThread-2 processing FiveExiting Thread-3Exiting Thread-1Exiting Thread-2Exiting Main ThreadPython XML解析什么是XML?XML 指可擴(kuò)展標(biāo)記語言(eXtensible Markup Language)失受。 你可以通過本站學(xué)習(xí)XML教程XML 被設(shè)計(jì)用來傳輸和存儲數(shù)據(jù)讶泰。XML是一套定義語義標(biāo)記的規(guī)則,這些標(biāo)記將文檔分成許多部件并對這些部件加以標(biāo)識贱纠。它也是元標(biāo)記語言峻厚,即定義了用于定義其他與特定領(lǐng)域有關(guān)的、語義的谆焊、結(jié)構(gòu)化的標(biāo)記語言的句法語言惠桃。python對XML的解析常見的XML編程接口有DOM和SAX,這兩種接口處理XML文件的方式不同辖试,當(dāng)然使用場合也不同辜王。python有三種方法解析XML,SAX罐孝,DOM呐馆,以及ElementTree:1.SAX (simple API for XML )python 標(biāo)準(zhǔn)庫包含SAX解析器,SAX用事件驅(qū)動(dòng)模型莲兢,通過在解析XML的過程中觸發(fā)一個(gè)個(gè)的事件并調(diào)用用戶定義的回調(diào)函數(shù)來處理XML文件汹来。2.DOM(Document Object Model)將XML數(shù)據(jù)在內(nèi)存中解析成一個(gè)樹续膳,通過對樹的操作來操作XML。3.ElementTree(元素樹)ElementTree就像一個(gè)輕量級的DOM收班,具有方便友好的API坟岔。代碼可用性好,速度快摔桦,消耗內(nèi)存少社付。注:因DOM需要將XML數(shù)據(jù)映射到內(nèi)存中的樹,一是比較慢邻耕,二是比較耗內(nèi)存鸥咖,而SAX流式讀取XML文件,比較快兄世,占用內(nèi)存少啼辣,但需要用戶實(shí)現(xiàn)回調(diào)函數(shù)(handler)。本章節(jié)使用到的XML實(shí)例文件movies.xml內(nèi)容如下:War, ThrillerDVD2003PG10Talk about a US-Japan warAnime, Science FictionDVD1989R8A schientific fictionAnime, ActionDVD4PG10Vash the Stampede!ComedyVHSPG2Viewable boredompython使用SAX解析xmlSAX是一種基于事件驅(qū)動(dòng)的API碘饼。利用SAX解析XML文檔牽涉到兩個(gè)部分:解析器和事件處理器熙兔。解析器負(fù)責(zé)讀取XML文檔,并向事件處理器發(fā)送事件,如元素開始跟元素結(jié)束事件;而事件處理器則負(fù)責(zé)對事件作出相應(yīng),對傳遞的XML數(shù)據(jù)進(jìn)行處理。1艾恼、對大型文件進(jìn)行處理;2麸锉、只需要文件的部分內(nèi)容钠绍,或者只需從文件中得到特定信息。3花沉、想建立自己的對象模型的時(shí)候柳爽。在python中使用sax方式處理xml要先引入xml.sax中的parse函數(shù),還有xml.sax.handler中的ContentHandler碱屁。ContentHandler類方法介紹characters(content)方法調(diào)用時(shí)機(jī):從行開始磷脯,遇到標(biāo)簽之前,存在字符娩脾,content的值為這些字符串赵誓。從一個(gè)標(biāo)簽,遇到下一個(gè)標(biāo)簽之前柿赊, 存在字符俩功,content的值為這些字符串。從一個(gè)標(biāo)簽碰声,遇到行結(jié)束符之前诡蜓,存在字符,content的值為這些字符串胰挑。標(biāo)簽可以是開始標(biāo)簽蔓罚,也可以是結(jié)束標(biāo)簽椿肩。startDocument()方法文檔啟動(dòng)的時(shí)候調(diào)用。endDocument()方法解析器到達(dá)文檔結(jié)尾時(shí)調(diào)用豺谈。startElement(name, attrs)方法遇到XML開始標(biāo)簽時(shí)調(diào)用覆旱,name是標(biāo)簽的名字,attrs是標(biāo)簽的屬性值字典核无。endElement(name)方法遇到XML結(jié)束標(biāo)簽時(shí)調(diào)用扣唱。make_parser方法以下方法創(chuàng)建一個(gè)新的解析器對象并返回。xml.sax.make_parser( [parser_list] )參數(shù)說明:parser_list - 可選參數(shù)团南,解析器列表parser方法以下方法創(chuàng)建一個(gè) SAX 解析器并解析xml文檔:xml.sax.parse( xmlfile, contenthandler[, errorhandler])參數(shù)說明:xmlfile - xml文件名contenthandler - 必須是一個(gè)ContentHandler的對象errorhandler - 如果指定該參數(shù)噪沙,errorhandler必須是一個(gè)SAX ErrorHandler對象parseString方法parseString方法創(chuàng)建一個(gè)XML解析器并解析xml字符串:xml.sax.parseString(xmlstring, contenthandler[, errorhandler])參數(shù)說明:xmlstring - xml字符串contenthandler - 必須是一個(gè)ContentHandler的對象errorhandler - 如果指定該參數(shù),errorhandler必須是一個(gè)SAX ErrorHandler對象Python 解析XML實(shí)例#!/usr/bin/python# -*- coding: UTF-8 -*-import xml.saxclass MovieHandler( xml.sax.ContentHandler ):? def __init__(self):? ? ? self.CurrentData = ""? ? ? self.type = ""? ? ? self.format = ""? ? ? self.year = ""? ? ? self.rating = ""? ? ? self.stars = ""? ? ? self.description = ""? # 元素開始事件處理? def startElement(self, tag, attributes):? ? ? self.CurrentData = tag? ? ? if tag == "movie":? ? ? ? print "*****Movie*****"? ? ? ? title = attributes["title"]? ? ? ? print "Title:", title? # 元素結(jié)束事件處理? def endElement(self, tag):? ? ? if self.CurrentData == "type":? ? ? ? print "Type:", self.type? ? ? elif self.CurrentData == "format":? ? ? ? print "Format:", self.format? ? ? elif self.CurrentData == "year": print "Year:", self.year? ? ? elif self.CurrentData == "rating":? ? ? ? print "Rating:", self.rating? ? ? elif self.CurrentData == "stars":? ? ? ? print "Stars:", self.stars? ? ? elif self.CurrentData == "description":? ? ? ? print "Description:", self.description? ? ? self.CurrentData = ""? # 內(nèi)容事件處理? def characters(self, content):? ? ? if self.CurrentData == "type":? ? ? ? self.type = content? ? ? elif self.CurrentData == "format":? ? ? ? self.format = content? ? ? elif self.CurrentData == "year":? ? ? ? self.year = content? ? ? elif self.CurrentData == "rating":? ? ? ? self.rating = content? ? ? elif self.CurrentData == "stars":? ? ? ? self.stars = content? ? ? elif self.CurrentData == "description":? ? ? ? self.description = content? if ( __name__ == "__main__"):? ? ? # 創(chuàng)建一個(gè) XMLReader? parser = xml.sax.make_parser()? # turn off namepsaces parser.setFeature(xml.sax.handler.feature_namespaces, 0)? # 重寫 ContextHandler? Handler = MovieHandler()? parser.setContentHandler( Handler )? ? ? parser.parse("movies.xml")以上代碼執(zhí)行結(jié)果如下:*****Movie*****Title: Enemy BehindType: War, ThrillerFormat: DVDYear: 2003Rating: PGStars: 10Description: Talk about a US-Japan war*****Movie*****Title: TransformersType: Anime, Science FictionFormat: DVDYear: 1989Rating: RStars: 8Description: A schientific fiction*****Movie*****Title: TrigunType: Anime, ActionFormat: DVDRating: PGStars: 10Description: Vash the Stampede!*****Movie*****Title: IshtarType: ComedyFormat: VHSRating: PGStars: 2Description: Viewable boredom完整的 SAX API 文檔請查閱Python SAX APIs使用xml.dom解析xml文件對象模型(Document Object Model吐根,簡稱DOM)正歼,是W3C組織推薦的處理可擴(kuò)展置標(biāo)語言的標(biāo)準(zhǔn)編程接口。一個(gè) DOM 的解析器在解析一個(gè) XML 文檔時(shí)拷橘,一次性讀取整個(gè)文檔局义,把文檔中所有元素保存在內(nèi)存中的一個(gè)樹結(jié)構(gòu)里,之后你可以利用DOM 提供的不同的函數(shù)來讀取或修改文檔的內(nèi)容和結(jié)構(gòu)冗疮,也可以把修改過的內(nèi)容寫入xml文件萄唇。python中用xml.dom.minidom來解析xml文件,實(shí)例如下:#!/usr/bin/python# -*- coding: UTF-8 -*-from xml.dom.minidom import parseimport xml.dom.minidom# 使用minidom解析器打開 XML 文檔DOMTree = xml.dom.minidom.parse("movies.xml")collection = DOMTree.documentElementif collection.hasAttribute("shelf"):? print "Root element : %s" % collection.getAttribute("shelf")# 在集合中獲取所有電影movies = collection.getElementsByTagName("movie")# 打印每部電影的詳細(xì)信息for movie in movies:? print "*****Movie*****"? if movie.hasAttribute("title"):? ? ? print "Title: %s" % movie.getAttribute("title")? type = movie.getElementsByTagName('type')[0]? print "Type: %s" % type.childNodes[0].data? format = movie.getElementsByTagName('format')[0]? print "Format: %s" % format.childNodes[0].data? rating = movie.getElementsByTagName('rating')[0]? print "Rating: %s" % rating.childNodes[0].data? description = movie.getElementsByTagName('description')[0]? print "Description: %s" % description.childNodes[0].data以上程序執(zhí)行結(jié)果如下:Root element : New Arrivals*****Movie*****Title: Enemy BehindType: War, ThrillerFormat: DVDRating: PGDescription: Talk about a US-Japan war*****Movie*****Title: TransformersType: Anime, Science FictionFormat: DVDRating: RDescription: A schientific fiction*****Movie*****Title: TrigunType: Anime, ActionFormat: DVDRating: PGDescription: Vash the Stampede!*****Movie*****Title: IshtarType: ComedyFormat: VHSRating: PGDescription: Viewable boredomPython GUI編程(Tkinter)Python 提供了多個(gè)圖形開發(fā)界面的庫术幔,幾個(gè)常用 Python GUI 庫如下:Tkinter: Tkinter 模塊(Tk 接口)是 Python 的標(biāo)準(zhǔn) Tk GUI 工具包的接口 .Tk 和 Tkinter 可以在大多數(shù)的 Unix 平臺下使用,同樣可以應(yīng)用在 Windows 和 Macintosh 系統(tǒng)里另萤。Tk8.0 的后續(xù)版本可以實(shí)現(xiàn)本地窗口風(fēng)格,并良好地運(yùn)行在絕大多數(shù)平臺中。wxPython:wxPython 是一款開源軟件诅挑,是 Python 語言的一套優(yōu)秀的 GUI 圖形庫四敞,允許 Python 程序員很方便的創(chuàng)建完整的、功能鍵全的 GUI 用戶界面拔妥。Jython:Jython 程序可以和 Java 無縫集成忿危。除了一些標(biāo)準(zhǔn)模塊,Jython 使用 Java 的模塊没龙。Jython 幾乎擁有標(biāo)準(zhǔn)的Python 中不依賴于 C 語言的全部模塊铺厨。比如,Jython 的用戶界面將使用 Swing兜畸,AWT或者 SWT努释。Jython 可以被動(dòng)態(tài)或靜態(tài)地編譯成 Java 字節(jié)碼。Tkinter 編程Tkinter 是 Python 的標(biāo)準(zhǔn) GUI 庫咬摇。Python 使用 Tkinter 可以快速的創(chuàng)建 GUI 應(yīng)用程序伐蒂。由于 Tkinter 是內(nèi)置到 python 的安裝包中、只要安裝好 Python 之后就能 import Tkinter 庫肛鹏、而且 IDLE 也是用 Tkinter 編寫而成逸邦、對于簡單的圖形界面 Tkinter 還是能應(yīng)付自如恩沛。注意:Python3.x 版本使用的庫名為 tkinter,即首寫字母 T 為小寫。import tkinter創(chuàng)建一個(gè)GUI程序1缕减、導(dǎo)入 Tkinter 模塊2雷客、創(chuàng)建控件3、指定這個(gè)控件的 master桥狡, 即這個(gè)控件屬于哪一個(gè)4搅裙、告訴 GM(geometry manager) 有一個(gè)控件產(chǎn)生了。實(shí)例:#!/usr/bin/python# -*- coding: UTF-8 -*-import Tkintertop = Tkinter.Tk()# 進(jìn)入消息循環(huán)top.mainloop()以上代碼執(zhí)行結(jié)果如下圖:實(shí)例2:#!/usr/bin/python# -*- coding: UTF-8 -*-from Tkinter import *? ? ? ? ? # 導(dǎo)入 Tkinter 庫root = Tk() # 創(chuàng)建窗口對象的背景色? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? # 創(chuàng)建兩個(gè)列表li? ? = ['C','python','php','html','SQL','java']movie? = ['CSS','jQuery','Bootstrap']listb? = Listbox(root)? ? ? ? ? #? 創(chuàng)建兩個(gè)列表組件listb2 = Listbox(root)for item in li: # 第一個(gè)小部件插入數(shù)據(jù)? ? listb.insert(0,item)for item in movie:? ? ? ? ? ? ? # 第二個(gè)小部件插入數(shù)據(jù)? ? listb2.insert(0,item)listb.pack()? ? ? ? ? ? ? ? ? ? # 將小部件放置到主窗口中l(wèi)istb2.pack()root.mainloop()? ? ? ? ? ? ? ? # 進(jìn)入消息循環(huán)以上代碼執(zhí)行結(jié)果如下圖:Tkinter 組件Tkinter的提供各種控件裹芝,如按鈕部逮,標(biāo)簽和文本框,一個(gè)GUI應(yīng)用程序中使用嫂易。這些控件通常被稱為控件或者部件兄朋。目前有15種Tkinter的部件。我們提出這些部件以及一個(gè)簡短的介紹怜械,在下面的表:標(biāo)準(zhǔn)屬性標(biāo)準(zhǔn)屬性也就是所有控件的共同屬性颅和,如大小,字體和顏色等等缕允。幾何管理Tkinter控件有特定的幾何狀態(tài)管理方法峡扩,管理整個(gè)控件區(qū)域組織,一下是Tkinter公開的幾何管理類:包灼芭、網(wǎng)格有额、位置Python2.x與3 .x版本區(qū)別Python的3 .0版本,常被稱為Python 3000彼绷,或簡稱Py3k。相對于Python的早期版本茴迁,這是一個(gè)較大的升級寄悯。為了不帶入過多的累贅,Python 3.0在設(shè)計(jì)的時(shí)候沒有考慮向下相容堕义。許多針對早期Python版本設(shè)計(jì)的程式都無法在Python 3.0上正常執(zhí)行猜旬。為了照顧現(xiàn)有程式,Python 2.6作為一個(gè)過渡版本倦卖,基本使用了Python 2.x的語法和庫洒擦,同時(shí)考慮了向Python 3.0的遷移,允許使用部分Python 3.0的語法與函數(shù)怕膛。新的Python程式建議使用Python 3.0版本的語法熟嫩。除非執(zhí)行環(huán)境無法安裝Python 3.0或者程式本身使用了不支援Python 3.0的第三方庫。目前不支援Python 3.0的第三方庫有Twisted, py2exe, PIL等褐捻。大多數(shù)第三方庫都正在努力地相容Python 3.0版本掸茅。即使無法立即使用Python 3.0椅邓,也建議編寫相容Python 3.0版本的程式,然后使用Python 2.6, Python 2.7來執(zhí)行昧狮。Python 3.0的變化主要在以下幾個(gè)方面:print 函數(shù)print語句沒有了景馁,取而代之的是print()函數(shù)。 Python 2.6與Python 2.7部分地支持這種形式的print語法逗鸣。在Python 2.6與Python 2.7里面合住,以下三種形式是等價(jià)的:print "fish"print ("fish") #注意print后面有個(gè)空格print("fish") #print()不能帶有任何其它參數(shù)然而,Python 2.6實(shí)際已經(jīng)支持新的print()語法:from __future__ import print_functionprint("fish", "panda", sep=', ')UnicodePython 2 有 ASCII str() 類型撒璧,unicode() 是單獨(dú)的透葛,不是 byte 類型。現(xiàn)在沪悲, 在 Python 3获洲,我們最終有了 Unicode (utf-8) 字符串,以及一個(gè)字節(jié)類:byte 和 bytearrays殿如。由于 Python3.X 源碼文件默認(rèn)使用utf-8編碼贡珊,這就使得以下代碼是合法的:>>> 中國 = 'china' >>>print(中國) chinaPython 2.x>>> str = "我愛北京天安門">>> str'\xe6\x88\x91\xe7\x88\xb1\xe5\x8c\x97\xe4\xba\xac\xe5\xa4\xa9\xe5\xae\x89\xe9\x97\xa8'>>> str = u"我愛北京天安門">>> stru'\u6211\u7231\u5317\u4eac\u5929\u5b89\u95e8'Python 3.x>>> str = "我愛北京天安門">>> str'我愛北京天安門'除法運(yùn)算Python中的除法較其它語言顯得非常高端,有套很復(fù)雜的規(guī)則涉馁。Python中的除法有兩個(gè)運(yùn)算符门岔,/和//首先來說/除法:在python 2.x中/除法就跟我們熟悉的大多數(shù)語言,比如Java啊C啊差不多烤送,整數(shù)相除的結(jié)果是一個(gè)整數(shù)寒随,把小數(shù)部分完全忽略掉,浮點(diǎn)數(shù)除法會保留小數(shù)點(diǎn)的部分得到一個(gè)浮點(diǎn)數(shù)的結(jié)果帮坚。在python 3.x中/除法不再這么做了妻往,對于整數(shù)之間的相除,結(jié)果也會是浮點(diǎn)數(shù)试和。Python 2.x:>>> 1 / 20>>> 1.0 / 2.00.5Python 3.x:>>> 1/20.5而對于//除法讯泣,這種除法叫做floor除法,會對除法的結(jié)果自動(dòng)進(jìn)行一個(gè)floor操作阅悍,在python 2.x和python 3.x中是一致的好渠。python 2.x:>>> -1 // 2-1python 3.x:>>> -1 // 2-1注意的是并不是舍棄小數(shù)部分,而是執(zhí)行floor操作节视,如果要截取小數(shù)部分拳锚,那么需要使用math模塊的trunc函數(shù)python 3.x:>>> import math>>> math.trunc(1 / 2)0>>> math.trunc(-1 / 2)0異常在 Python 3 中處理異常也輕微的改變了,在 Python 3 中我們現(xiàn)在使用 as 作為關(guān)鍵詞寻行。捕獲異常的語法由 except exc, var 改為 except exc as var霍掺。使用語法except (exc1, exc2) as var可以同時(shí)捕獲多種類別的異常。 Python 2.6已經(jīng)支持這兩種語法。1. 在2.x時(shí)代抗楔,所有類型的對象都是可以被直接拋出的棋凳,在3.x時(shí)代,只有繼承自BaseException的對象才可以被拋出连躏。2. 2.x raise語句使用逗號將拋出對象類型和參數(shù)分開剩岳,3.x取消了這種奇葩的寫法,直接調(diào)用構(gòu)造函數(shù)拋出對象即可入热。在2.x時(shí)代拍棕,異常在代碼中除了表示程序錯(cuò)誤,還經(jīng)常做一些普通控制結(jié)構(gòu)應(yīng)該做的事情勺良,在3.x中可以看出绰播,設(shè)計(jì)者讓異常變的更加專一,只有在錯(cuò)誤發(fā)生的情況才能去用異常捕獲語句來處理尚困。xrange在 Python 2 中 xrange() 創(chuàng)建迭代對象的用法是非常流行的蠢箩。比如: for 循環(huán)或者是列表/集合/字典推導(dǎo)式轩端。這個(gè)表現(xiàn)十分像生成器(比如坠狡。"惰性求值")募寨。但是這個(gè) xrange-iterable 是無窮的蒿柳,意味著你可以無限遍歷。由于它的惰性求值乒疏,如果你不得僅僅不遍歷它一次盖高,xrange() 函數(shù) 比 range() 更快(比如 for 循環(huán))听想。盡管如此邦马,對比迭代一次贱鼻,不建議你重復(fù)迭代多次,因?yàn)樯善髅看味紡念^開始滋将。在 Python 3 中邻悬,range() 是像 xrange() 那樣實(shí)現(xiàn)以至于一個(gè)專門的 xrange() 函數(shù)都不再存在(在 Python 3 中 xrange() 會拋出命名異常)。import timeitn = 10000def test_range(n):? ? return for i in range(n):? ? ? ? passdef test_xrange(n):? ? for i in xrange(n):? ? ? ? pass? Python 2print 'Python', python_version()print '\ntiming range()' %timeit test_range(n)print '\n\ntiming xrange()' %timeit test_xrange(n)Python 2.7.6timing range()1000 loops, best of 3: 433 μs per looptiming xrange()1000 loops, best of 3: 350 μs per loopPython 3print('Python', python_version())print('\ntiming range()')%timeit test_range(n)Python 3.4.1timing range()1000 loops, best of 3: 520 μs per loopprint(xrange(10))---------------------------------------------------------------------------NameError? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? Traceback (most recent call last)in()----> 1 print(xrange(10))NameError: name 'xrange' is not defined八進(jìn)制字面量表示八進(jìn)制數(shù)必須寫成0o777随闽,原來的形式0777不能用了拘悦;二進(jìn)制必須寫成0b111。新增了一個(gè)bin()函數(shù)用于將一個(gè)整數(shù)轉(zhuǎn)換成二進(jìn)制字串橱脸。 Python 2.6已經(jīng)支持這兩種語法。在Python 3.x中分苇,表示八進(jìn)制字面量的方式只有一種添诉,就是0o1000。python 2.x>>> 0o1000512>>> 01000512python 3.x>>> 01000? File "", line 1? ? 01000? ? ? ? ^SyntaxError: invalid token>>> 0o1000512不等運(yùn)算符Python 2.x中不等于有兩種寫法 != 和 <>Python 3.x中去掉了<>, 只有!=一種寫法医寿,還好栏赴,我從來沒有使用<>的習(xí)慣去掉了repr表達(dá)式``Python 2.x 中反引號``相當(dāng)于repr函數(shù)的作用Python 3.x 中去掉了``這種寫法,只允許使用repr函數(shù)靖秩,這樣做的目的是為了使代碼看上去更清晰么须眷?不過我感覺用repr的機(jī)會很少竖瘾,一般只在debug的時(shí)候才用,多數(shù)時(shí)候還是用str函數(shù)來用字符串描述對象花颗。def sendMail(from_: str, to: str, title: str, body: str) -> bool:? ? pass多個(gè)模塊被改名(根據(jù)PEP8)StringIO模塊現(xiàn)在被合并到新的io模組內(nèi)捕传。 new, md5, gopherlib等模塊被刪除。 Python 2.6已經(jīng)支援新的io模組扩劝。httplib, BaseHTTPServer, CGIHTTPServer, SimpleHTTPServer, Cookie, cookielib被合并到http包內(nèi)庸论。取消了exec語句,只剩下exec()函數(shù)棒呛。 Python 2.6已經(jīng)支援exec()函數(shù)聂示。5.數(shù)據(jù)類型1)Py3.X去除了long類型,現(xiàn)在只有一種整型——int簇秒,但它的行為就像2.X版本的long2)新增了bytes類型鱼喉,對應(yīng)于2.X版本的八位串,定義一個(gè)bytes字面量的方法如下:>>> b = b'china' >>> type(b)
str對象和bytes對象可以使用.encode() (str -> bytes) or .decode() (bytes -> str)方法相互轉(zhuǎn)化趋观。
>>> s = b.decode()
>>> s
'china'
>>> b1 = s.encode()
>>> b1
b'china'
3)dict的.keys()扛禽、.items 和.values()方法返回迭代器,而之前的iterkeys()等函數(shù)都被廢棄拆内。同時(shí)去掉的還有 dict.has_key()旋圆,用 in替代它吧 。
Python IDE
本文為大家推薦幾款款不錯(cuò)的 Python IDE(集成開發(fā)環(huán)境)麸恍,比較推薦 PyCharm灵巧,當(dāng)然你可以根據(jù)自己的喜好來選擇適合自己的 Python IDE。
PyCharm
PyCharm 是由 JetBrains 打造的一款 Python IDE抹沪。
PyCharm 具備一般 Python IDE 的功能刻肄,比如:調(diào)試、語法高亮融欧、項(xiàng)目管理敏弃、代碼跳轉(zhuǎn)、智能提示噪馏、自動(dòng)完成麦到、單元測試、版本控制等欠肾。
另外瓶颠,PyCharm 還提供了一些很好的功能用于 Django 開發(fā),同時(shí)支持 Google App Engine刺桃,更酷的是粹淋,PyCharm 支持 IronPython。
PyCharm 官方下載地址:http://www.jetbrains.com/pycharm/download/
效果圖查看:
Sublime Text
Sublime Text 具有漂亮的用戶界面和強(qiáng)大的功能,例如代碼縮略圖桃移,Python 的插件屋匕,代碼段等。還可自定義鍵綁定借杰,菜單和工具欄过吻。
Sublime Text 的主要功能包括:拼寫檢查,書簽第步,完整的 Python API 疮装, Goto 功能,即時(shí)項(xiàng)目切換粘都,多選擇廓推,多窗口等等。
Sublime Text 是一個(gè)跨平臺的編輯器翩隧,同時(shí)支持 Windows樊展、Linux、Mac OS X等操作系統(tǒng)堆生。
使用Sublime Text 2的插件擴(kuò)展功能专缠,你可以輕松的打造一款不錯(cuò)的 Python IDE,以下推薦幾款插件(你可以找到更多):
CodeIntel:自動(dòng)補(bǔ)全+成員/方法提示(強(qiáng)烈推薦)
SublimeREPL:用于運(yùn)行和調(diào)試一些需要交互的程序(E.G. 使用了Input()的程序)
Bracket Highlighter:括號匹配及高亮
SublimeLinter:代碼pep8格式檢查
Eclipse+Pydev
1淑仆、安裝Eclipse
Eclipse可以在它的官方網(wǎng)站Eclipse.org找到并下載涝婉,通常我們可以選擇適合自己的Eclipse版本,比如Eclipse Classic蔗怠。下載完成后解壓到到你想安裝的目錄中即可墩弯。
當(dāng)然在執(zhí)行Eclipse之前,你必須確認(rèn)安裝了Java運(yùn)行環(huán)境,即必須安裝JRE或JDK寞射,你可以到(http://www.java.com/en/download/manual.jsp)找到JRE下載并安裝渔工。
2、安裝Pydev
運(yùn)行Eclipse之后桥温,選擇help-->Install new Software引矩,如下圖所示。
點(diǎn)擊Add侵浸,添加pydev的安裝地址:http://pydev.org/updates/旺韭,如下圖所示。
完成后點(diǎn)擊"ok"掏觉,接著點(diǎn)擊PyDev的"+"茂翔,展開PyDev的節(jié)點(diǎn),要等一小段時(shí)間履腋,讓它從網(wǎng)上獲取PyDev的相關(guān)套件,當(dāng)完成后會多出PyDev的相關(guān)套件在子節(jié)點(diǎn)里,勾選它們?nèi)缓蟀磏ext進(jìn)行安裝遵湖。如下圖所示悔政。
安裝完成后,重啟Eclipse即可
3延旧、設(shè)置Pydev
安裝完成后谋国,還需要設(shè)置一下PyDev,選擇Window -> Preferences來設(shè)置PyDev迁沫。設(shè)置Python的路徑芦瘾,從Pydev的Interpreter - Python頁面選擇New
會彈出一個(gè)窗口讓你選擇Python的安裝位置,選擇你安裝Python的所在位置集畅。
完成之后PyDev就設(shè)置完成近弟,可以開始使用。
4挺智、建立Python Project:
安裝好Eclipse+PyDev以后祷愉,我們就可以開始使用它來開發(fā)項(xiàng)目了。首先要?jiǎng)?chuàng)建一個(gè)項(xiàng)目赦颇,選擇File -> New ->Pydev Project
會彈出一個(gè)新窗口二鳄,填寫Project Name,以及項(xiàng)目保存地址媒怯,然后點(diǎn)擊next完成項(xiàng)目的創(chuàng)建订讼。
5、創(chuàng)建新的Pydev Module
光有項(xiàng)目是無法執(zhí)行的扇苞,接著必須創(chuàng)建新的Pydev Moudle欺殿,選擇File -> New -> Pydev Module
在彈出的窗口中選擇文件存放位置以及Moudle Name,注意Name不用加.py杨拐,它會自動(dòng)幫助我們添加祈餐。然后點(diǎn)擊Finish完成創(chuàng)建。
輸入"hello world"的代碼哄陶。
6帆阳、執(zhí)行程序
程序?qū)懲旰螅覀兛梢蚤_始執(zhí)行程序,在上方的工具欄上面找到執(zhí)行的按鈕屋吨。
之后會彈出一個(gè)讓你選擇執(zhí)行方式的窗口蜒谤,通常我們選擇Python Run,開始執(zhí)行程序至扰。
更多 Python IDE
推薦10 款最好的 Python IDE:http://www.runoob.com/w3cnote/best-python-ide-for-developers.html
當(dāng)然還有非常多很棒的 Python IDE鳍徽,你可以自由的選擇,更多 Python IDE 請參閱:http://wiki.python.org/moin/PythonEditors
Python JSON
本章節(jié)我們將為大家介紹如何使用 Python 語言來編碼和解碼 JSON 對象敢课。
JSON(JavaScript Object Notation) 是一種輕量級的數(shù)據(jù)交換格式阶祭,易于人閱讀和編寫绷杜。
JSON 函數(shù)
使用 JSON 函數(shù)需要導(dǎo)入 json 庫:import json。
json.dumps
json.dumps 用于將 Python 對象編碼成 JSON 字符串濒募。
語法
json.dumps(obj, skipkeys=False, ensure_ascii=True, check_circular=True, allow_nan=True, cls=None, indent=None, separators=None, encoding="utf-8", default=None, sort_keys=False, **kw)
實(shí)例
以下實(shí)例將數(shù)組編碼為 JSON 格式數(shù)據(jù):
#!/usr/bin/python
import json
data = [ { 'a' : 1, 'b' : 2, 'c' : 3, 'd' : 4, 'e' : 5 } ]
json = json.dumps(data)
print json
以上代碼執(zhí)行結(jié)果為:
[{"a": 1, "c": 3, "b": 2, "e": 5, "d": 4}]
使用參數(shù)讓 JSON 數(shù)據(jù)格式化輸出:
>>> import json
>>> print json.dumps({'a': 'Runoob', 'b': 7}, sort_keys=True, indent=4, separators=(',', ': '))
{
? ? "a": "Runoob",
? ? "b": 7
}
python 原始類型向 json 類型的轉(zhuǎn)化對照表:
json.loads
json.loads 用于解碼 JSON 數(shù)據(jù)鞭盟。該函數(shù)返回 Python 字段的數(shù)據(jù)類型。
語法
json.loads(s[, encoding[, cls[, object_hook[, parse_float[, parse_int[, parse_constant[, object_pairs_hook[, **kw]]]]]]]])
實(shí)例
以下實(shí)例展示了Python 如何解碼 JSON 對象:
#!/usr/bin/python
import json
jsonData = '{"a":1,"b":2,"c":3,"d":4,"e":5}';
text = json.loads(jsonData)
print text
以上代碼執(zhí)行結(jié)果為:
{u'a': 1, u'c': 3, u'b': 2, u'e': 5, u'd': 4}
json 類型轉(zhuǎn)換到 python 的類型對照表:
更多內(nèi)容參考:https://docs.python.org/2/library/json.html瑰剃。
使用第三方庫:Demjson
Demjson 是 python 的第三方模塊庫齿诉,可用于編碼和解碼 JSON 數(shù)據(jù),包含了 JSONLint 的格式化及校驗(yàn)功能晌姚。
Github 地址:https://github.com/dmeranda/demjson
官方地址:http://deron.meranda.us/python/demjson/
環(huán)境配置
在使用 Demjson 編碼或解碼 JSON 數(shù)據(jù)前粤剧,我們需要先安裝 Demjson 模塊。本教程我們會下載 Demjson 并安裝:
$ tar -xvzf demjson-2.2.3.tar.gz
$ cd demjson-2.2.3
$ python setup.py install
更多安裝介紹查看:http://deron.meranda.us/python/demjson/install
JSON 函數(shù)
encode
Python encode() 函數(shù)用于將 Python 對象編碼成 JSON 字符串挥唠。
語法
demjson.encode(self, obj, nest_level=0)
實(shí)例
以下實(shí)例將數(shù)組編碼為 JSON 格式數(shù)據(jù):
#!/usr/bin/python
import demjson
data = [ { 'a' : 1, 'b' : 2, 'c' : 3, 'd' : 4, 'e' : 5 } ]
json = demjson.encode(data)
print json
以上代碼執(zhí)行結(jié)果為:
[{"a":1,"b":2,"c":3,"d":4,"e":5}]
decode
Python 可以使用 demjson.decode() 函數(shù)解碼 JSON 數(shù)據(jù)抵恋。該函數(shù)返回 Python 字段的數(shù)據(jù)類型。
語法
demjson.decode(self, txt)
實(shí)例
以下實(shí)例展示了Python 如何解碼 JSON 對象:
#!/usr/bin/python
import demjson
json = '{"a":1,"b":2,"c":3,"d":4,"e":5}';
text = demjson.decode(json)
print? text
以上代碼執(zhí)行結(jié)果為:
{u'a': 1, u'c': 3, u'b': 2, u'e': 5, u'd': 4}
Python 100例
以下實(shí)例在Python2.7下測試通過