python连接数据库示例(东西写得很详细,剽过来了)
原文鏈接:http://tech.it168.com/a2009/1014/759/000000759444.shtml
?
【 IT168 技術文檔】本文將向讀者詳細介紹如何利用DB-API模塊方便地開發MySQL腳本。我們首先介紹了有關 軟件的安裝方法,隨后分別用兩個實例對DB-API模塊做了深入的介紹,最后討論了用Python DB-API編寫的MySQL腳本的移植注意事項。一、DB-API簡介
Python語言是一種流行的開源編程語言,不僅自身表達能力強,而且還有許多輔助模塊,著極大的增強了其功能。本文介紹的是一個名為DB-API的模塊——顧名思義,該模塊為開發人員提供了數據庫應用編程接口。DB-API旨在幫應用開發人員擺脫特定數據庫引擎的具體細節的糾纏,編寫出能夠在不同數據庫引擎之間相互移植的數據庫訪問腳本。
DB-API的設計與Perl和Ruby的DBI模塊、PHP 的PEAR DB 類以及Java的JDBC接口非常類似,它使用了一個兩層體系結構,其中頂層提供了一個抽象接口,該接口可以泛用于所有支持的數據庫引擎;而底層則是有一些特定引擎的驅動程序構成,這些驅動程序負責處理與特定引擎有關的細節。這樣的話,為了使用DB-API來編寫Python腳本,必須有相應的驅動程序來處理特定的數據庫系統。對于MySQL來說,DB-API使用驅動程序MySQLdb來處理對MySQL數據庫的訪問。下面我們將首先詳細介紹驅動程序的安裝,然后闡述如何編寫DB-API腳本。
二、安裝MySQLdb
為了用DB-API編寫MySQL腳本,必須確保已經安裝了Python。對于UNIX操作系統來說,通常都安裝有該軟件,但是Windows系統的話就難說了。其實Python的安裝很簡單,先到Python官方網站下載安裝程序,然后一路回車即可。
就本文而言,我們要求使用Python 2.3.4或更高版本,并且還得安裝MySQLdb模塊。我們可以從命令行提示符(這里的提示符為UNIX操作系統中的%,如果是Windows系統的話,該提示符則為C:\>)中輸入下列命令來檢查兩者的安裝情況,命令如下所示:
% pythonPython 2.4.3 (#1, Aug 29 2006, 14:45:33)[GCC 3.4.6 (Gentoo 3.4.6-r1, ssp-3.4.5-1.0, pie-8.7.9)] on linux2Type "help", "copyright", "credits" or "license" for more information.>>> import MySQLdb
假如Python的版本滿足要求,并且輸入import MySQLdb命令(即導入MySQLdb模塊)后沒有出現錯誤報告的話,我們就可以開始編寫訪問數據庫的腳本了;但是,如果出現下列錯誤消息的話,則說明還缺少MySQLdb,所以必須先下載安裝MySQLdb模塊:
為了獲得MySQLdb,請訪問http://sourceforge.net/projects/mysql-python,從這里可選擇適合您的平臺的安裝包,分為預編譯的二進制文件和源代碼安裝包。如果您選擇二進制文件發行版本的話,安裝過程基本安裝提示即可完成。如果從源代碼進行安裝的話,則需要切換到MySQLdb發行版本的頂級目錄,并鍵入下列命令。在UNIX操作系統之下安裝的時候,第二條命令需要以超級用戶的身份運行才能將驅動程序文件復制到Python的安裝目錄中。具體命令如下所示:
三、我們第一個DB-API腳本
腳本使用MySQLdb的DB-API訪問MySQL的時候,通常要經過以下步驟:
l 導入MySQLdb模塊
l 打開一個MySQL服務器連接
l 發出查詢語句并回收查詢結果
l 關閉服務器連接
下面我們通過一個簡單的DB-API腳本對這些步驟進行說明。編寫腳本時,可以使用文本編輯程序建立一個文件,將其命名為server_version.py,然后用它來存放下面的腳本。這個腳本利用MySQLdb實現與MySQL服務器的交互,它的任務很簡單,那就是詢問服務器的版本字符串:
# server_version.py - 檢索并顯示數據庫服務器版本
import MySQLdbconn = MySQLdb.connect (host = "localhost",user = "testuser",passwd = "testpass",db = "test")cursor = conn.cursor ()cursor.execute ("SELECT VERSION()")row = cursor.fetchone ()print "server version:", row[0]cursor.close ()conn.close ()
Import語句告訴Python該腳本需要MySQLdb模塊中的代碼。注意,導入語句必須放置在連接MySQL服務器的語句之前。然后,使用相應連接參數來調用MySQLdb驅動程序的connect()方法,這些參數包括運行MySQL的服務器的主機名,我們MySQL帳戶對應的用戶名和口令,以及我們要使用的數據庫的名稱。Connect()的參數語法會隨著驅動程序的不同而不同,對于MySQLdb來說,這些參數可以通過name = value的格式提供,這樣的話,我們就可以不同的順序來提供參數。server_version.py會在本地主機上建立一個到達MySQL服務器的連接,并利用用戶名和口令即testuser和testpass來訪問我們的數據庫test,如下所示:
如果調用connect()成功,它會返回一個連接對象,為進一步與MySQL交互做好準備。如果調用失敗,它會拋出一個異常。注意,我們的server_version.py腳步并沒有處理該異常,所以碰到錯誤時該腳本就會終止。具體的錯誤處理將在后面加以介紹。
獲得連接對象之后,server_version.py會調用該對象的cursor()方法來創建一個游標對象來處理語句。該腳本利用這個游標發送一個SELECT VERSION()語句,該語句會返回一個包含有服務器版本信息的字符串,如下所示:
cursor = conn.cursor ()cursor.execute ("SELECT VERSION()")row = cursor.fetchone ()print "server version:", row[0]cursor.close ()
該游標對象的execute()方法能將向服務器發送語句,而fetchone()方法則檢索回一行數據,該數據作為元組處理。對于這里的語句,該元組包含一個單一的值,這個值將被該腳本打印出來。如果無法取得數據行,fetchone()將返回None值;這種情況的處理我們將在后面加以介紹。游標對象可用于發出多個語句,但是server_version.py獲取版本字符串之后就不再需要該游標了,所以我們將其關閉即可。
最后,該腳本調用連接對象的close()方法關閉到服務器的連接,如下所示:
conn.close ()
之后,conn將被廢棄,所以就無法再使用它來訪問服務器了。
若要執行server_version.py腳本,可以從命令行調用Python,并給出該腳本的名稱即可。之后,我們將看到類似如下所示的輸出:
% python server_version.pyserver version: 5.1.12-log
這表明該MySQL服務器的版本是5.1.12;后綴-log說明查詢日志記錄功能已被啟用。當然,實際上您可能會看到其他后綴,這要視您使用的數據庫服務器而定。舉例來說,后綴-beta表示該發行版本的穩定級別;如果您啟用了調試功能,您就會在運行結果中看到-debug后綴。
所以可以建立腳本,這樣可以通過其名稱來運行之,而無需顯式調用Python。在UNIX操作系統之下,可以為腳本開頭部分添加一個#!行,用以規定Python解釋器的完整路徑。這樣的話,系統就知道應使用哪個程序來執行此腳本。舉例來說,如果Python解釋器位于/usr/bin/python,那么可在腳本的第一行添加如下所示的內容:
#!/usr/bin/python
然后,使用chmod把該腳本變成可執行文件,這樣我們就能通過下列命令來直接運行腳本:
% chmod +x server_version.py% ./server_version.py
其中,先導的./的作用是顯式告訴命令解釋程序:該腳本位于當前目錄中,這樣做是因為許多UNIX操作系統的帳戶沒有配置成在當前目錄搜索命令。
在Windows操作系統中,無需#!行開頭,不過即使加了這一行也沒有關系,所以如果要把運行在UNIX系統的腳本移植到Windows系統的時候,無需對它進行修改。不過,與使用chmod將.py腳本變為可執行文件不同,我們需要把以.py結尾的文件與Python關聯在一起,為此,可以在控制面板中打開“工具”菜單下的“文件夾選項”,單擊文件類型選項卡, 在此,將以.py作為擴展名的文件設置成使用Python打開。這樣一來,我們就可以通過腳本的名稱來調用它了,如下所示:
C:\> server_version.py
如果在 Windows 上安裝的是ActiveState Python,那么ActiveState的安裝程序會在安裝過程中自動完成此關聯過程。
四、更復雜的DB-API腳本
前面的示例腳本Server_version.py有許多缺點,比如,它沒有捕捉異常,也不能在出錯時指出到底是什么樣的錯誤,此外,它也不允許執行語句時不返回任何結果。下面通過一個更加“高級”的腳本animal.py來演示如何解決這些問題,這里給出完整的animal.py代碼。
#animal.py:創建動物表并從中檢索信息import sysimport MySQLdb#連接到MySQL服務器try:conn = MySQLdb.connect (host = "localhost",user = "testuser",passwd = "testpass",db = "test")except MySQLdb.Error, e:print "Error %d: %s" % (e.args[0], e.args[1])sys.exit (1)#創建動物表并填充內容try:cursor = conn.cursor ()cursor.execute ("DROP TABLE IF EXISTS animal")cursor.execute ("""CREATE TABLE animal(name CHAR(40),category CHAR(40))""")cursor.execute ("""INSERT INTO animal (name, category)VALUES('snake', 'reptile'),('frog', 'amphibian'),('tuna', 'fish'),('racoon', 'mammal')""")print "Number of rows inserted: %d" % cursor.rowcount#使用fetchone()進行循環提取cursor.execute ("SELECT name, category FROM animal")while (1):row = cursor.fetchone ()if row == None:breakprint "%s, %s" % (row[0], row[1])print "Number of rows returned: %d" % cursor.rowcount#使用fetchall()進行循環提取cursor.execute ("SELECT name, category FROM animal")rows = cursor.fetchall ()for row in rows:print "%s, %s" % (row[0], row[1])print "Number of rows returned: %d" % cursor.rowcount#發出修改名稱的語句,共兩種方式,第一種是在語句字符串#中使用數據值的字面值,第二種是使用位置標識符cursor.execute ("""UPDATE animal SET name = 'turtle'WHERE name = 'snake'""")print "Number of rows updated: %d" % cursor.rowcountcursor.execute ("""UPDATE animal SET name = %sWHERE name = %s""", ("snake", "turtle"))print "Number of rows updated: %d" % cursor.rowcount#創建一個字典游標,這樣就可以使用位置而非名稱來訪問數據列中的值了。cursor.close ()cursor = conn.cursor (MySQLdb.cursors.DictCursor)cursor.execute ("SELECT name, category FROM animal")result_set = cursor.fetchall ()for row in result_set:print "%s, %s" % (row["name"], row["category"])print "Number of rows returned: %d" % cursor.rowcountcursor.close ()except MySQLdb.Error, e:print "Error %d: %s" % (e.args[0], e.args[1])sys.exit (1)conn.commit ()conn.close ()
該腳本使用一個表來存儲動物的名稱和類別:
本例中的表和一些語句取自于PEAR DB的說明文檔。腳本animal.py的開頭部分如下所示,從#!行可以看出它是打算運行于UNIX系統的:
如同Server_version.py一樣,這個腳本也導入了MySQLdb,此外,它還導入了sys模塊以供錯誤處理之用。如果發生錯誤,animal.py就會利用sys.exit()返回1來表明腳本異常結束。
下面介紹錯誤處理。導入必要的模塊之后,animal.py使用connect()調用建立到服務器的連接。為了處理連接故障,比如,顯示故障的原因,該腳本必須捕捉異常。在Python語言中,為了處理異常,必須把代碼放到try語句中,并且包括一個except子句來包含錯誤處理代碼。生成的連接的代碼如下所示:
try:conn = MySQLdb.connect (host = "localhost",user = "testuser",passwd = "testpass",db = "test")except MySQLdb.Error, e:print "Error %d: %s" % (e.args[0], e.args[1])sys.exit (1)
Except子句中的異常類MySQLdb.Error用于取得MySQLdb可以提供的具體數據庫錯誤信息,而變量e則用來存放錯誤信息。如果出現異常,MySQLdb會把有關信息存入e.args——這是一個包含錯誤代碼和描述該錯誤的字符串組成的雙元素元組。在本例中,except子句會打印這些值,然后退出。
任何數據庫有關的語句都可以放入類似的try/except結構中來收集和報告錯誤,為了簡便起見,后面的討論中不再顯示異常處理代碼。
接下來介紹用于發送語句的方法。Animal.py接下來的代碼將創建一個游標對象,并利用它發送設置和填充動物表的語句。這部分代碼如下所示:
cursor = conn.cursor ()cursor.execute ("DROP TABLE IF EXISTS animal")cursor.execute ("""CREATE TABLE animal(name CHAR(40),category CHAR(40))""")cursor.execute ("""INSERT INTO animal (name, category)VALUES('snake', 'reptile'),('frog', 'amphibian'),('tuna', 'fish'),('racoon', 'mammal')""")print "Number of rows inserted: %d" % cursor.rowcount
需要注意的是,這里的代碼沒有包含錯誤檢查。請記住,它們可以放入try語句,這樣一旦出錯就會觸發異常,繼而被except子句所捕獲并處理。但是考慮到代碼的可讀性,我們這里只給出了代碼的主干部分。上面的語句將完成以下動作:
l 動物表已經存在,則丟棄它。
l 創建動物表。
l 向表中插入一些數據,并報告添加的行數。
這些語句都是通過調用游標對象的execute()方法發出的。其中前兩個execute()語句不會生成數據,但是第三個語句將生成一個表示已經插入行數的統計量。這個統計數字存放在游標的rowcount屬性中。有些數據庫接口是通過execution運行調用的返回值來提供這個統計數字的,但是DB-API卻不是這樣。
此動物表已經建好,所以我們可以發出選擇指令來從中檢索信息了。如同前面的語句一樣,SELECT語句也要使用execute()方法發出。然而,與DROP或者INSERT語句不同的是,SELECT語句會生成一個結果集合,也就是說,execute()僅僅發出語句,但是卻沒有返回結果集合。我們可以使用fetchone()方法每次返回一行數據,或者使用fetchall()方法一次全部搞定。在animal.py中,這兩者方法都用到了。下面是如何使用fetchone()每次檢索一行數據的方法:
cursor.execute ("SELECT name, category FROM animal")while (1):row = cursor.fetchone ()if row == None:breakprint "%s, %s" % (row[0], row[1])print "Number of rows returned: %d" % cursor.rowcount
方法fetchone()會把結果集合的下一行作為一個元組返回,如果已經到了結果集合的末尾的話,就返回值None。這里的循環會進行相應的檢查,并在取盡結果集合的時候退出。對于返回的每一行,元組包含了兩個值,Print語句會打印輸出每個元組元素。然而,因為它們是安裝在元組中的順序使用的,所以Print語句正好可以如下編寫:
顯示此語句結果之后,腳本還會顯示返回的行數,即rowcount屬性的值。
Fetchall()可以把整個結果集合作為以元組為元素的元組一次返回,或者,如果結果集合為空則會返回一個空的元組。為了訪問個別數據行,可以枚舉fetchall()返回的行集合,具體代碼如下所示:
cursor.execute ("SELECT name, category FROM animal")rows = cursor.fetchall ()for row in rows:print "%s, %s" % (row[0], row[1])print "Number of rows returned: %d" % cursor.rowcount
上面通過訪問rowcount來打印行數。當fetchall()的時候,另一種確定行數的方法是使用它返回的值的長度,如下所示:
前面的循環語句中是把數據行作為元組看待的,如果我們將其作為字典處理的話,就可以通過名字來訪問各列的值了。以下代碼展示了這一過程。需要注意的是,訪問字典需要一種不同的游標,所以這里關閉了原來的游標,并利用一個不同的游標類獲得了一個新游標,如下所示:
結果集合中的空值將作為None返回。MySQLdb支持位置標識符功能,利用它可以在語句字符串之內為數據值綁定特殊標記。這就為直接向語句中嵌入值提供了替代方法。位置標識符機制會給數據值添加引號,并逸出出現在這些值內的所有的特殊字符。下面的示例演示了一個把蛇改成海龜的UPDATE語句,首先使用的是字面值,然后使用的是位置標識符。其中使用字面值的語句看上去是這樣的:
另外,我們還可以使用位置標識符標記%s,并為其捆綁相應的值的方式來發送這個語句,代碼如下所示:
這里是上面的execute()調用方式的注意事項:
l 每個位置標識符%s對應于一個插入該語句字符串的值。
l 指示符%s不應該用引號括住,MySQLdb會根據需要添加引號。
l 綁定給位置標識符的值放在一個元組中,它們在元組中的順序就是出現在語句中的順序。如果只有一個值x的話,可以寫作(x,),表示這是個單元素元組。
l 可以給位置標識符綁定一個None值,這表示向該語句中插入一個SQL空值。
發出有關語句之后,animal.py將關閉此游標,確認修改,并斷開跟服務器的連接,如下所示:
cursor.execute ("""
UPDATE animal SET name = %s
WHERE name = %s
""", ("snake", "turtle"))
print "Number of rows updated: %d" % cursor.rowcount連接對象的commit()方法確保當前事務中的修改已經在數據庫中完成。在DB-API中,autocommit模式被禁用了,所以在斷開連接之前必須調用commit(),否則所作修改可能會丟失。
如果動物表是一個MyISAM表,commit()就不起作用了:MyISAM是一種非事務性存儲引擎,所以對MyISAM表的修改會立即生效,與autocommit模式無關。如果使用了事務性存儲引擎,當斷開連接的時候如果不調用commit()會導致一個隱式的事務回滾。舉例來說,如果我們在CREATE TABLE語句后面加上ENGINE = InnoDB,并刪除腳本末尾處的commit()調用,就會發現腳本運行后animal為空。
對于僅僅檢索數據的腳本,由于不用對修改進行確認,所以commit()對它們來說也是不需要的。
五、關于移植事項
如果希望把基于MySQLdb的DB-API腳本移植到不同的數據庫,則要需要修改的地方主要是出現驅動程序名稱的地方:
1. 用于導入驅動模塊的import語句,必須進行修改以便導入相應的驅動程序。
2. 連接數據庫服務器的connect()調用。此connect()方法是通過驅動模塊的名稱進行訪問的,所以驅動程序名稱需要更改。此外,connect()參數語法也會隨著驅動程序的不同而變化。
3. 異常處理。在except子句中的異常類也是通過驅動程序名稱引用的,所以也要根據需要進行相應的修改。
進行移植時,除了驅動程序名稱之外還有一些地方要注意,那就是位置標識符。DB-API規范允許使用某些位置標識符語法,但是一些驅動程序使用的語法確不同于MySQLdb支持的語法。
六、小結
本文向讀者詳細介紹如何利用DB-API模塊方便地開發MySQL腳本。我們首先介紹了有關軟件的安裝方法,隨后分別用兩個實例對DB-API模塊做了深入的介紹,最后討論了用Python DB-API編寫的MySQL腳本的移植注意事項。希望本文能夠對您有所幫助。
點此發表你的看法>>【已有0位網友?
總結
以上是生活随笔為你收集整理的python连接数据库示例(东西写得很详细,剽过来了)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: svn st小解(以偶工作中遇到问题为例
- 下一篇: python语言中,对于cursor的查