用python處理文字,本地檔案系統以及使用資料庫的知識基礎

中大黑熊發表於2014-07-04

主要是想通過python之流的指令碼語言來進行檔案系統的遍歷,處理文字以及使用簡易資料庫的操作。

本文基於陳皓的:《程式設計師技術練級攻略》

 

一.Python csv

對於電子表格和資料庫匯出檔案,比較常見的檔案格式是.csv,所以python中的csv模組也是一個比較重要的模組。下面介紹csv常用的方法。

1.csv.reader(csvfile, dialect='excel', **fmtparams)

  • 該函式返回一個reader物件,能夠以行遍歷的形式遍歷行裡面的資料。
  • csvfile——需要是支援迭代(Iterator)的物件,並且每次呼叫next方法的返回值是字串(string),通常的檔案(file)物件,或者列表(list)物件都是適用的,如果是檔案物件,開啟是需要加"b"標誌引數。
  • dialect——編碼風格,預設為excel方式,也就是逗號(,)分隔,另外csv模組也支援excel-tab風格,也就是製表符(tab)分隔。其它的方式需要自己 定義,然後可以呼叫register_dialect方法來註冊,以及list_dialects方法來查詢已註冊的所有編碼風格列表。
  • fmtparams——格式化引數,用來覆蓋之前dialect物件指定的編碼風格

看一下示例:

#!/usr/bin/env python
#-*- coding:utf-8 -*-

import csv

#定義一個字串
st = "I am a student."
#定義列表,注意csv只接受以ACSII編碼的字串序列
li = [1,2,3,4,5]  #不符合要求
lis = ['a','b','c']

reader1 = csv.reader(st)
for line in reader1:
    print line,   #['I'] [' '] ['a'] ['m'] [' '] ['a'] [' '] ['s'] ['t'] ['u'] ['d'] ['e'] ['n'] ['t'] ['.']

print '\n'+str(reader1.line_num)   #輸出行數

reader2 = csv.reader(lis)
for line in reader2:
    print line,

#開啟檔案物件
with open ('./egg.csv','rb') as csvfile:
    reader3 = csv.reader(csvfile)
    for row in reader3:
        print row,

對於每個line或row支援next,dialectfieldnamesline_num方法。

2.csv.writer(csvfile, dialect='excel', **fmtparams)

參數列同上,注意在建立了writer物件之後,要通過writerow寫入一行,而通過writerows寫入多行。

#!/usr/bin/env python
#-*- coding:utf-8 -*-

import csv

#注:with語句有兩個作用:1.關閉檔案控制程式碼;2.更好的處理異常
with open('./egg.csv','wb') as csvfile:  #注:w是重新覆蓋,a是直接追加 
    writer = csv.writer(csvfile)
    writer.writerow(['姓名','年齡','電話'])
    data = [('何輝宇','21','1234'),('何輝寧','21','5678')]
    writer.writerows(data)

 

3.dialect

csv 模組巧妙地運用 dialect 的概念,將不同應用程式對 CSV 處理方式上的差異隱藏起來。

這裡的差異指的是欄位分隔字元(delimiter)跟識別資料內容的引號(quoting character)等。目前 csv 模組內建兩種 dialect - excel (.csv) 及 excel-tab (.tsv),可以用來讀取 Excel 寫出、或是寫出 Excel 可以讀取的檔案格式,而不用去管 Excel 慣用的格式為何。

 

4.class csv.DictReader(csvfile, fieldnames=None, restkey=None, restval=None, dialect='excel', *args, **kwds)

跟reader差不多,只不過是以字典形式呈現。

#!/usr/bin/env python
#-*- coding:utf-8 -*-

import csv

with open('./egg.csv','rb') as csvfile:
    reader = csv.DictReader(csvfile)
    for line in reader:
        print line,

結果:

dzhwen@deng:~/python檔案/csv$ python dictreader.py
{'\xe7\x94\xb5\xe8\xaf\x9d': '1234', '\xe5\xb9\xb4\xe9\xbe\x84': '21', '\xe5\xa7\x93\xe5\x90\x8d': '\xe4\xbd\x95\xe8\xbe\x89\xe5\xae\x87'} {'\xe7\x94\xb5\xe8\xaf\x9d': '5678', '\xe5\xb9\xb4\xe9\xbe\x84': '21', '\xe5\xa7\x93\xe5\x90\x8d': '\xe4\xbd\x95\xe8\xbe\x89\xe5\xae\x81'}

 

5.class csv.DictWriter(csvfile, fieldnames, restval='', extrasaction='raise', dialect='excel', *args, **kwds)

與之類似。

 

二.Python open

1.內建函式open()

file_object = open(file_name,access_mode = 'r',buffering = -1)

檔案物件的訪問模式:

  • r——讀方式
  • w——寫方式
  • a——追加模式
  • r+,w+,a+——以讀寫模式開啟
  • rb,wb,ab——以二進位制模式讀寫追加
  • rb+,wb+,ab+——以二進位制讀寫模式開啟

 

2.工廠函式file()

open()和file()函式具有相同的功能,可以任意替換。您所看到任何使用open()的地方,都可以使用file()替換它。

 

3.輸入/輸出

read(size),readline(),readlines(),write()

 

4.檔案內移動

  • file.seek(off,whence=0)——在檔案中移動檔案指標,從whence(0代表檔案起始,1代表當前位置,2代表檔案末尾)偏移off位元組。
  • file.tell()——返回當前在檔案中的位置

5.檔案迭代

for eachLine in f:

  pass

6.其他

  • file.close() —— 關閉檔案
  • file.fileno() —— 返回檔案的描述符(file descriptor,FD,整型值)
  • file.flush() —— 直接把內部緩衝區中的資料立刻寫入檔案,而不是被動地等待輸出緩衝區被寫入。

三.Python sys

sys模組中的函式非常多,挑幾個有用的來講講。

1.sys.argv —— 對命令列引數的訪問

  • sys.argv是命令列引數的列表
  • len(sys.argv) 是命令列引數個數(也就是argc)

2.sys.platform() —— 輸出平臺資訊

>>> import sys
>>> sys.platform
'linux2'

實現一個清除終端,linux下用clear,windows下用cls

#!/usr/bin/env python
#-*- coding:utf-8 -*-

import sys

ostype = sys.platform()
if ostype == "linux" or ostype == "linux2":
    cmd = "clear"
else:
    cmd = "cls"

3.sys.exit(n) 

執行至主程式的末尾時,直譯器會自動退出. 但是如果需要中途退出程式, 你可以呼叫sys.exit 函式, 它帶有一個可選的整數引數返回給呼叫它的程式. 這意味著你可以在主程式中捕獲對sys.exit 的呼叫。(注:0是正常退出,其他為不正常,可拋異常事件供捕獲!)(相當與C++的return函式)

 

#!/usr/bin/env python
#-*- coding:utf-8 -*-

import sys

def exitfunc(value):
    print value
    sys.exit(0)

print "hello"

try:
    sys.exit(1)
except SystemExit,value:
    exitfunc(value)

print "come?

4.sys.path —— 與程式有關的執行路徑

>>> import sys
>>> sys.path
['', '/usr/local/lib/python2.7/dist-packages/tornado-1.2.1-py2.7.egg', '/usr/local/lib/python2.7/dist-packages/uWSGI-2.0.3-py2.7.egg', '/usr/local/lib/python2.7/dist-packages/python_memcached-1.53-py2.7.egg', '/usr/local/lib/python2.7/dist-packages/protobuf-2.5.0-py2.7.egg', '/usr/lib/python2.7', '/usr/lib/python2.7/plat-linux2', '/usr/lib/python2.7/lib-tk', '/usr/lib/python2.7/lib-old', '/usr/lib/python2.7/lib-dynload', '/usr/local/lib/python2.7/dist-packages', '/usr/lib/python2.7/dist-packages', '/usr/lib/python2.7/dist-packages/PIL', '/usr/lib/python2.7/dist-packages/gst-0.10', '/usr/lib/python2.7/dist-packages/gtk-2.0', '/usr/lib/pymodules/python2.7', '/usr/lib/python2.7/dist-packages/ubuntu-sso-client', '/usr/lib/python2.7/dist-packages/ubuntuone-client', '/usr/lib/python2.7/dist-packages/ubuntuone-control-panel', '/usr/lib/python2.7/dist-packages/ubuntuone-couch', '/usr/lib/python2.7/dist-packages/ubuntuone-installer', '/usr/lib/python2.7/dist-packages/ubuntuone-storage-protocol']

新增模組路徑:

sys.path.append(“mine module path”).

5.sys.modules —— python的所有模組

使用方法:

>>> sys.modules

常用方法:

for names in sys.modules.keys():
if names != ’sys’:
    pass

5.sys.stdin,stdout,stderr —— 標準輸入輸出,錯誤輸出

標準輸入和標準錯誤 (通常縮寫為 stdoutstderr) 是內建在每一個 UNIX 系統中的管道。

當你 print 某些東西時,結果前往 stdout 管道;

當你的程式崩潰並列印出除錯資訊 (例如 Python 中的 traceback (錯誤跟蹤)) 的時候,資訊前往 stderr 管道。

  • stdout 是一個類檔案物件;呼叫它的 write 函式可以列印出你給定的任何字串。
  • 實際上,這就是 print 函式真正做的事情;它在你列印的字串後面加上一個硬回車,然後呼叫 sys.stdout.write 函式。在最簡單的例子中,stdoutstderr 把它們的輸出傳送到相同的地方。
  • stdout 一樣,stderr 並不為你新增硬回車;如果需要,要自己加上。
  • stdoutstderr 都是類檔案物件,但是它們都是隻寫的。它們都沒有 read 方法,只有 write 方法。然而,它們仍然是類檔案物件,因此你可以將其它任何 (類) 檔案物件賦值給它們來重定向其輸出。

>>> import sys
>>> for i in range(3):
...     print 'Hello!'
... 
Hello!
Hello!
Hello!
>>> for i in range(3):
...     sys.stdout.write('Hello!')
... 
Hello!Hello!Hello! 
>>> for i in range(3):
...     sys.stderr.write('Hello!')
... 
Hello!Hello!Hello!

使用sys重定向輸出

#!/usr/bin/env python
#-*- coding:utf-8 -*-

import sys

print 'Dive in'        # 標準輸出
saveout = sys.stdout        # 終在重定向前儲存stdout,這樣的話之後你還可以將其設回正常
fsock = open('out.log', 'w')      # 開啟一個新檔案用於寫入。如果檔案不存在,將會被建立。如果檔案存在,將被覆蓋。
sys.stdout = fsock                 # 所有後續的輸出都會被重定向到剛才開啟的新檔案上。
print  'This message will be logged instead of displayed'    # 這樣只會將輸出結果“列印”到日誌檔案中;螢幕上不會看到輸出
sys.stdout = saveout   # 在我們將 stdout 搞亂之前,讓我們把它設回原來的方式。     
fsock.close()     # 關閉日誌檔案。

使用sys.stdin讀取

>>> r = sys.stdin.readline()
sasasa
>>> r
'sasasa\n'

重定向錯誤資訊

fsock = open('error.log', 'w')           # 開啟你要儲存除錯資訊的日誌檔案。 
sys.stderr = fsock                           # 將新開啟的日誌檔案的檔案物件賦值給stderr以重定向標準錯誤。
raise Exception, 'this error will be logged'   # 引發一個異常,沒有在螢幕上列印出任何東西,所有正常的跟蹤資訊已經寫進error.log
#還要注意你既沒有顯式關閉日誌檔案,也沒有將 stderr 設回最初的值。
#這樣挺好,因為一旦程式崩潰 (由於引發的異常),Python 將替我們清理並關閉檔案

列印到 stderr——向標準錯誤寫入錯誤資訊是很常見的,所以有一種較快的語法可以立刻匯出資訊

>>> print 'entering function'
entering function
>>> import sys
>>> print >> sys.stderr, 'entering function'

entering function 

print 語句的快捷語法可以用於寫入任何開啟的檔案 (或者是類檔案物件)。

在這裡,你可以將單個print語句重定向到stderr而且不用影響後面的print語句。

 

四.Python os,path

os 模組的檔案/目錄訪問函式

檔案處理

  • mkfifo()/mknod() —— 建立命名管道/建立檔案系統節點
  • remove()/unlink() —— 刪除檔案
  • rename()/renames() —— 重新命名檔案
  • stat() —— 返回檔案資訊
  • symlink() —— 建立符號連結
  • utime() —— 更新時間戳
  • tmpfile() —— 建立並開啟('w'+'b')一個新的臨時檔案
  • walk() —— 生成一個目錄樹下的所有檔名

目錄/資料夾

  • chdir() —— 改變當前工作目錄
  • chroot() —— 改變當前程式的根目錄
  • listdir() —— 列出指定目錄的檔案
  • getcwd() —— 返回當前工作目錄
  • mkdir()/makedirs() —— 建立目錄/建立多層目錄
  • rmdir()/removedirs() —— 刪除目錄/刪除多層目錄

 訪問/許可權

  • access() —— 檢驗許可權模式
  • chmod() —— 改變許可權模式
  • chown() —— 改變owner和GID,但不會跟蹤連結
  • umask() —— 設定預設許可權模式

檔案描述符操作

  • open() —— 開啟檔案
  • read() / write() —— 讀取/寫入檔案

os.path 模組的檔案/目錄訪問函式

分隔

  • basename() —— 去掉目錄路徑,返回檔名
  • dirname() —— 去掉檔名,返回目錄路徑
  • join() —— 將分離的各部分組合成一個路徑名
  • split() —— 返回(dirname(),basename())元組
  • splitdrive() —— 返回(drivename,pathname)元組
  • splitext —— 返回(filename,extension)元組

資訊

  • getatime() —— 返回最近訪問時間
  • getctime() —— 返回檔案建立時間
  • getmtime() —— 返回最近檔案修改時間
  • getsize() —— 返回檔案大小(以位元組為單位)

查詢

  • exists() —— 指定路徑(檔案或目錄)是否存在
  • isabs() —— 指定路徑是否為絕對路徑
  • isdir() —— 指定路徑是否存在且為一個目錄
  • isfile() —— 指定路徑是否存在且為一個檔案
  • islink() —— 指定路徑是否存在且為一個符號連結
  • ismount —— 指定路徑是否存在且為一個掛載點
  • samefile —— 兩個路徑名是否指向同一個檔案

五.Python sqlite

Sqllite是一個小巧的內嵌型資料庫,也就是說沒有獨立的維護程式。

1.匯入模組

>>> import sqlite3

2. 建立/開啟資料庫

可以開啟資料庫:

cx = sqlite3.connect('./test.db')

也可以存在記憶體當中:

con = sqlite3.connect(":memory:")

3.資料庫連線物件

開啟資料庫時返回的物件cx就是一個資料庫連線物件,它可以有以下操作:

  1. commit()--事務提交   
  2. rollback()--事務回滾   
  3. close()--關閉一個資料庫連線   
  4. cursor()--建立一個遊標

關於commit(),如果isolation_level隔離級別預設,那麼每次對資料庫的操作,都需要使用該命令,你也可以設定isolation_level=None,這樣就變為自動提交模式。

4.使用遊標查詢資料庫
定義遊標:
cu = cx.cursor()

遊標物件有以下的操作:

  1. execute()--執行sql語句   
  2. executemany--執行多條sql語句   
  3. close()--關閉遊標   
  4. fetchone()--從結果中取一條記錄,並將遊標指向下一條記錄   
  5. fetchmany()--從結果中取多條記錄   
  6. fetchall()--從結果中取出所有記錄   
  7. scroll()--遊標滾動  

 

5.建表

>>> cu.execute('Create Table users(login varchar(8),uid integer)')
<sqlite3.Cursor object at 0xb71db5e0>

 

6.插入資料

>>> cu.execute('Insert into users values("join",100)')
<sqlite3.Cursor object at 0xb71db5e0>

請注意避免以下寫法:

# Never do this -- insecure 會導致注入攻擊

pid=200
c.execute("... where pid = '%s'" % pid)

正確的做法如下,如果t只是單個數值,也要採用t=(n,)的形式,因為元組是不可變的。

for t in[(0,10,'abc','Yu'),(1,20,'cba','Xu')]:
    cx.execute("insert into catalog values (?,?,?,?)", t)

簡單的插入兩行資料,不過需要提醒的是,只有提交了之後,才能生效.我們使用資料庫連線物件cx來進行提交commit和回滾rollback操作.

>>> cx.commit()

 

7.查詢

>>> cu.execute('Select * From Users')
<sqlite3.Cursor object at 0xb71db5e0>
>>> for eachUser in cu.fetchall():
...     print eachUser
... 
(u'join', 100)
(u'jane', 110)

 

8.修改
>>> cu.execute('Update Users set login="Betty" where uid = 110')
<sqlite3.Cursor object at 0xb71db5e0>
>>> cu.execute('Select * From Users')
<sqlite3.Cursor object at 0xb71db5e0>
>>> for eachUser in cu.fetchall():
...     print eachUser
... 
(u'join', 100)
(u'Betty', 110)
>>> cx.commit()

 

9.刪除

>>> cu.execute('Delete from Users where uid = 110')
<sqlite3.Cursor object at 0xb71db5e0>
>>> cu.execute('Select * From Users')
<sqlite3.Cursor object at 0xb71db5e0>
>>> for eachUser in cu.fetchall():
...     print eachUser
... 
(u'join', 100)
>>> cx.commit()

 

10.單獨取一行

>>> cu.execute('Select * From Users')
<sqlite3.Cursor object at 0xb71db5e0>
>>> r = cu.fetchone()
>>> type(r)
<type 'tuple'>
>>> r
(u'join', 100)
>>> r[0]
u'join'
>>> r[1]
100

 

程式碼彙總:

 

>>> import sqlite3
>>> cx = sqlite3.connect('./test.db')
>>> cu = cx.cursor()
>>> cu.execute('Create Table users(login varchar(8),uid integer)')
<sqlite3.Cursor object at 0xb71db5e0>
>>> cu.execute('Insert into users values("join",100)')
<sqlite3.Cursor object at 0xb71db5e0>
>>> cu.execute('Insert into users values("jane",110)')
<sqlite3.Cursor object at 0xb71db5e0>
>>> cx.commit()
>>> cu.execute('Select * From Users')
<sqlite3.Cursor object at 0xb71db5e0>
>>> for eachUser in cu.fetchall():
...     print eachUser
... 
(u'join', 100)
(u'jane', 110)
>>> cu.execute('Update Users set login="Betty" where uid = 110')
<sqlite3.Cursor object at 0xb71db5e0>
>>> cu.execute('Select * From Users')
<sqlite3.Cursor object at 0xb71db5e0>
>>> for eachUser in cu.fetchall():
...     print eachUser
... 
(u'join', 100)
(u'Betty', 110)
>>> cx.commit()
>>> cu.execute('Delete from Users where uid = 110')
<sqlite3.Cursor object at 0xb71db5e0>
>>> cu.execute('Select * From Users')
<sqlite3.Cursor object at 0xb71db5e0>
>>> for eachUser in cu.fetchall():
...     print eachUser
... 
(u'join', 100)
>>> cx.commit()
>>> cu.execute('Select * From Users')
<sqlite3.Cursor object at 0xb71db5e0>
>>> r = cu.fetchone()
>>> type(r)
<type 'tuple'>
>>> r
(u'join', 100)
>>> r[0]
u'join'
>>> r[1]
100

 

終於寫完了,累趴了。

轉載請註明出處:http://www.cnblogs.com/sysu-blackbear/  謝謝!

 


 

 

相關文章