python網(wǎng)絡(luò)編程學(xué)習(xí)筆記(九):數(shù)據(jù)庫客戶端 DB-API
一、DB-API概述
python支持很多不同的數(shù)據(jù)庫。由于不同的賣家服務(wù)器導(dǎo)致和數(shù)據(jù)庫通信的網(wǎng)絡(luò)協(xié)議各有不同。在python的早期版本中,每一種數(shù)據(jù)庫都帶有自己的python模塊,所有這些模塊以不同的方式工作,并提供不同的函數(shù)。這種方法不便于編寫能夠在多種數(shù)據(jù)庫服務(wù)器類型中運(yùn)行的代碼,于是DB-API庫函數(shù)產(chǎn)生。在DB-API中,所有連接數(shù)據(jù)庫的模塊即便是底層網(wǎng)絡(luò)協(xié)議不同,也會(huì)提供一個(gè)共同的接口。這一點(diǎn)和JAVA中的JDBC和ODBC類似。
DB-API下載地址:http://wiki.python.org/moin/DatabaseProgramming,目前版本是2.0,支持?jǐn)?shù)據(jù)庫包括IBM DB2、Firebird (and Interbase) 、Informix、Ingres、MySQL、Oracle 、PostgreSQL 、SAP DB (also known as "MaxDB") 、Microsoft SQL Server 、Sybase 等。
二、數(shù)據(jù)庫連接
1、PostgreSQL
有幾個(gè)模塊可以完成python與PostgreSQL的聯(lián)接,這里主要介紹使用psycopg。
下載地址是:http://initd.org/psycopg/download/。如果沒有PostgreSQL,可以從以下地址下載:http://www.postgresql.org/。(關(guān)于PostgreSQL的安裝等更加詳細(xì)的介紹,可以見http://wenku.baidu.com/view/8e32d10c6c85ec3a87c2c500.html。)連接PostgreSQL數(shù)據(jù)庫:
import psycopg2
print "connecting to test"##test為數(shù)據(jù)庫名
dbh=psycopg2.connect('dbname=test user=postgres')
print "connection successful"
2、MySQL
對(duì)于MySQL,python的接口是已知的MySQLdb或者M(jìn)ySQL-Python,下載地址:http://sourceforge.net/projects/mysql-python/。與PostgreSQL不同的是,MySQLdb connect()函數(shù)可以帶各種參數(shù),具體如下:
參數(shù) | 說明 |
user | 用戶名,默認(rèn)為當(dāng)前登錄用戶。 |
passwd | 用戶密碼,沒有默認(rèn)的。 |
db | 連接的數(shù)據(jù)庫名。 |
host | 數(shù)據(jù)庫主機(jī)名。 |
port | TCP端口,默認(rèn)是3306。 |
舉例,連接test數(shù)據(jù)庫:
import MySQLdb
print "connecting..."
dbh=MySQLdb.connect(db="test")
print "connection successful."
dbh.close()
三、簡單操作(以PostgreSQL為例)
這里以PostgreSQL為例介紹創(chuàng)建表、查詢表等操作。例子中數(shù)據(jù)庫名為test,用戶名為postgres,輸入一個(gè)表名,向表中插入數(shù)據(jù)并進(jìn)行查詢。具體如下,已進(jìn)行了注示:
import psycopg2
print "connecting to test"
dbh=psycopg2.connect('dbname=test user=postgres')
print "connection successful"
cur=dbh.cursor()#建立一個(gè)cursor對(duì)象,返回?cái)?shù)據(jù)為字典形式
a=raw_input('table list:')#輸入表名
cur.execute("CREATE TABLE %s(myid integer UNIQUE,filename varchar(255))" %a)#生成表,包含一個(gè)字段filename
b=1c='201210310540'
cur.execute("INSERT INTO %s VALUES (%d,%s)"%(a,b,c))#向表中插入記錄b,c
cur.execute("SELECT * FROM %s " %a)#查詢表中內(nèi)容
rows=cur.fetchall()#獲得結(jié)果集中的所有行
for row in rows:
print row
dbh.commit()#以上對(duì)數(shù)據(jù)庫的操作事務(wù)生效
dbh.close()
1、事務(wù)
多數(shù)數(shù)據(jù)庫支持事務(wù),事務(wù)可以將多條對(duì)數(shù)據(jù)庫的改動(dòng)放在一條命令中。在上面的例子中,當(dāng)未曾執(zhí)行commit()命令時(shí),以上對(duì)數(shù)據(jù)庫的操作均不會(huì)生效。另外還有一個(gè)函數(shù)rollback(),這個(gè)函數(shù)可以有效的放棄上一次執(zhí)行commit()或者rollback()之后的改動(dòng)。這個(gè)函數(shù)在發(fā)現(xiàn)錯(cuò)誤,并想放棄已經(jīng)發(fā)出的事務(wù)時(shí),非常有效。對(duì)于不支持事務(wù)的數(shù)據(jù)庫,改變會(huì)立刻執(zhí)行,commit()什么也不做,但rollback()會(huì)報(bào)錯(cuò)。
2、效率
執(zhí)行事件的性能很大程序上取決于不同的服務(wù)器,一般來說,在每個(gè)單獨(dú)的命令后都提交是更新數(shù)據(jù)庫最慢的方法,但如果一次提交很大數(shù)據(jù)又會(huì)使服務(wù)器產(chǎn)生buffer溢出。因此,應(yīng)該合理處理提交的數(shù)量。
四、參數(shù)風(fēng)格
在上面的例子中,使用了printf()一樣的類型格式。但實(shí)際上,在DB-API中,不同的數(shù)據(jù)庫所支持的參數(shù)風(fēng)絡(luò)不同,必須選擇合適的方法,否則程序不會(huì)執(zhí)行。下面的方法,可以知道當(dāng)前所支持的類型格式。
>>> import psycopg2
>>> print psycopg2.paramstyle
pyformat這一結(jié)果可以看出,當(dāng)前支持pyformat格式。
針對(duì)DB-API說明書,以使用頻度由小變大的順序介紹:
qmark | 表示question-mark風(fēng)格。指令字符串中的數(shù)據(jù)的每一位都被用一個(gè)問號(hào)替換,參數(shù)以list或tuple的形式給出。例如:INSERT INTO ch14 VALUES (?, ?)。 |
format | 使用和printf()一樣的類型格式,不支持對(duì)于指定參數(shù)Python的擴(kuò)展名。它帶一個(gè)list或tuple來轉(zhuǎn)換。例如:INSERT INTO ch14 VALUES(%d, %s) |
numeric | 表示numeric風(fēng)格。指令字符串中的數(shù)據(jù)的每一位都被一個(gè)后面是數(shù)字的冒號(hào)替換(數(shù)字以1開始),參數(shù)以list或tuple的形式給出。例如:INSERT INTO ch14 VALUES(:1, :2) |
named | 表示named風(fēng)格。和numeric類似,但是在冒號(hào)后面用名稱取代數(shù)字。帶一個(gè)dictionary用來轉(zhuǎn)換。例如:INSERT INTO ch14 VALUES(:number, :text) |
pyformat | 支持Python風(fēng)格的參數(shù),帶dictionary用來轉(zhuǎn)換。例如:INSERT INTO ch14 VALUES(%(number)d, %(text)s)。 |
五、重復(fù)指令
1、execute和executemany()
例子:
將下面的數(shù)據(jù)插入到test數(shù)據(jù)庫中:
12 Twelve
13 Thirteen
14 Fourteen
15 Fifteen
(1)execute一條條插入
cur.execute("INSERT INTO test VALUES (12, 'Twelve')")
cur.execute("INSERT INTO test VALUES (13, 'Thirteen')")
cur.execute("INSERT INTO test VALUES (14, 'Fourteen')")
cur.execute("INSERT INTO test VALUES (15, 'Fifteen')")
這種方法過于低效。
(2)executemany()函數(shù)帶一個(gè)指令和一列指令運(yùn)行的記錄。列表上的每條記錄要么是一個(gè)list,要么是一個(gè)dictionary。
import psycopg2
print "connecting to test"
dbh=psycopg2.connect('dbname=test user=postgres')
print "connection successful"
cur=dbh.cursor()
rows = ({'num': 0, 'text': 'Zero'},
{'num': 1, 'text': 'Item One'},
{'num': 2, 'text': 'Item Two'},
{'num': 3, 'text': 'Three'})
cur.executemany("INSERT INTO test VALUES (%(num)d, %(text)s)", rows)
dbh.commit()
dbh.close()
executemany()主要的缺點(diǎn)是,在需要執(zhí)行指令前把所有的記錄放在內(nèi)存中。如果數(shù)據(jù)大的話,這就是一個(gè)問題,它會(huì)占有系統(tǒng)的所有內(nèi)存資源。如果executemany()不能滿足需要,那么除了execute()之外,還是有可能取得性能優(yōu)化的。根據(jù)DB-API說明,當(dāng)execute()被周期性調(diào)用時(shí),數(shù)據(jù)庫后端可以執(zhí)行優(yōu)化。但是它的第一個(gè)參數(shù)必須指向同一個(gè)對(duì)象,而不是一個(gè)含有相同值的字符串,即在內(nèi)存中的同一個(gè)字符串對(duì)象。和executemany()一樣,這樣并不能保證優(yōu)化,并且也不能期望execute()運(yùn)行得比executemany()快。但是如果不能使用executemany(),這就是一個(gè)最好的選擇。
六、fetchall、fetchmany、fetchone獲取數(shù)據(jù)
fetchall(self):接收全部的返回結(jié)果行。
fetchmany(self, size=None):接收size條返回結(jié)果行.如果size的值大于返回的結(jié)果行的數(shù)量,則會(huì)返回cursor.arraysize條數(shù)據(jù)。
fetchone(self):返回一條結(jié)果行。
七、獲取metadata(元數(shù)據(jù))
元數(shù)據(jù)的英文名稱是“Metadata",它是“關(guān)于數(shù)據(jù)的數(shù)據(jù)”。如在上面的例子中,Metadata的結(jié)果為:
Column(name='id', type_code=23, display_size=None, internal_size=4, precision=None, scale=None, null_ok=None)
Column(name='filename', type_code=1043, display_size=None, internal_size=255, precision=None, scale=None, null_ok=None)
import psycopg2
print "connecting to bbstime"
dbh=psycopg2.connect('dbname=bbstime user=postgres')
print "connection successful"
cur=dbh.cursor()
cur.execute("SELECT * FROM asd")
for column in cur.description:
print column
dbh.close()
八、計(jì)算行數(shù)
方法有兩種,一種是用len(),一種是用rowcount。
import psycopg2
print "connecting to bbstime"
dbh=psycopg2.connect('dbname=bbstime user=postgres')
print "connection successful"
cur=dbh.cursor()
cur.execute("SELECT * FROM test")
rows=cur.fetchall()
print len(rows)#利用len來計(jì)算行數(shù)
print "rows:",cur.rowcount#利用rowcount來計(jì)算行數(shù)
dbh.close()
- Python udp網(wǎng)絡(luò)程序?qū)崿F(xiàn)發(fā)送、接收數(shù)據(jù)功能示例
- Python大數(shù)據(jù)之網(wǎng)絡(luò)爬蟲的post請(qǐng)求、get請(qǐng)求區(qū)別實(shí)例分析
- Python 網(wǎng)絡(luò)編程之UDP發(fā)送接收數(shù)據(jù)功能示例【基于socket套接字】
- 詳解Python3網(wǎng)絡(luò)爬蟲(二):利用urllib.urlopen向有道翻譯發(fā)送數(shù)據(jù)獲得翻譯結(jié)果
- Python下載網(wǎng)絡(luò)文本數(shù)據(jù)到本地內(nèi)存的四種實(shí)現(xiàn)方法示例
- Python爬蟲實(shí)例_城市公交網(wǎng)絡(luò)站點(diǎn)數(shù)據(jù)的爬取方法
- python網(wǎng)絡(luò)編程調(diào)用recv函數(shù)完整接收數(shù)據(jù)的三種方法
- python網(wǎng)絡(luò)編程之?dāng)?shù)據(jù)傳輸U(kuò)DP實(shí)例分析
- python如何獲取網(wǎng)絡(luò)數(shù)據(jù)
相關(guān)文章
Python錯(cuò)誤NameError:name?'X'?is?not?defined的解決方法
這篇文章主要給大家介紹了關(guān)于Python錯(cuò)誤NameError:name?‘X‘?is?not?defined的解決方法,這是最近工作中遇到的一個(gè)問題,文中通過實(shí)例代碼將解決的方法介紹的非常詳細(xì),需要的朋友可以參考下2023-03-03pycharm部署django項(xiàng)目到云服務(wù)器的詳細(xì)流程
今天重點(diǎn)給大家介紹pycharm部署django項(xiàng)目到云服務(wù)器的詳細(xì)流程,首先大家需要先下載python3.8壓縮包,然后通過一系列命令完成操作,具體實(shí)現(xiàn)方法,跟隨小編一起看看吧2021-06-06Python偏函數(shù)Partial function使用方法實(shí)例詳解
這篇文章主要介紹了Python偏函數(shù)Partial function使用方法實(shí)例詳解,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-06-06Python實(shí)現(xiàn)解析命令行參數(shù)的常見方法總結(jié)
除ide的執(zhí)行方式外,命令行的方式執(zhí)行Python腳本是參數(shù)化程序執(zhí)行的一種常見且簡單的方法。本文總結(jié)了三個(gè)常見的獲取和解析命令行參數(shù)的方法,需要的可以參考一下2022-10-10Python畫柱狀統(tǒng)計(jì)圖操作示例【基于matplotlib庫】
這篇文章主要介紹了Python畫柱狀統(tǒng)計(jì)圖操作,結(jié)合實(shí)例形式分析了Python基于matplotlib庫實(shí)現(xiàn)圖形繪制的相關(guān)操作技巧,需要的朋友可以參考下2018-07-07Python機(jī)器學(xué)習(xí)之隨機(jī)梯度下降法的實(shí)現(xiàn)
如果當(dāng)我們數(shù)據(jù)量和樣本量非常大時(shí),每一項(xiàng)都要參與到梯度下降,那么它的計(jì)算量時(shí)非常大的,所以我們需要采用隨機(jī)梯度下降法。本文介紹了Python實(shí)現(xiàn)隨機(jī)梯度下降法的方法,希望對(duì)大家有所幫助2023-02-02