python 文件處理、數據持久化與正則

1、文件的處理python

  數據持久化最簡單的類型就是普通文件,有時也叫作平面文件(flat file)。文件是計算機中由OS(操做系統)管理的具備名字的存儲區域,在linux系統上,文件被看做是字節序列。linux

fileobj=open(filename, mode,buffering=-1,...)    打開文件 
web

  fileobj是open()函數返回的文件對象正則表達式

  filename須要打開的文件的字符串名shell

  buffering:是否使用緩存,0表示輸出無緩存,1表示使用緩存;json

    負數表示使用默認設置,正數表示使用近似指定的大小。緩存

  mode指定文件的打開模式:less

    r表示讀模式ide

    r+表示可讀寫文件。【可讀;可寫;可追加】函數

    w表示寫模式,若是文件不存在則新建立,若是存在則從新些內容

    w+,寫讀

    x表示文件不存在的狀況下新建立並寫文件。

    a表示文件若是存在,在文件末尾追加內容。

    "U"表示在讀取時,能夠將 \r \n \r\n自動轉換成 \n (與 r 或 r+ 模式同使用)

    mode的第二個字母表明文件的類型:t表明文本類型,b表明二進制文件

文件的操做方法:

f.read([n]) 作多讀取n個字節
f.readline([n]) 讀取單行輸入的作多n個字節,若是省略n,該方法將讀取整行
f.readlines([size]) 讀取全部行並返回一個列表,size可選,用於指定在讀取操做中止前在文件上讀取的近似字符數
f.write(s) 寫入字符串
f.writelines(lines) 寫入序列lines中的全部字符串
f.close() 關閉文件
f.tell 返回當前文件的指針
f.seek(offset [,whence])

跳轉到文件其餘字節偏移量的位置

  whence:0(默認)表示從開頭偏移offset個字節

  whence:1表示從當前位置處偏移offset個字節

  whence:2表示從距離文件結尾處偏移offset個字節

f.isatty() 若是f是一個交互式終端,則返回1
f.flush()
清除輸出緩衝區
f.truncate([size])
將文件截斷爲最多size字節
f.fileno()
返回一個整數描述符
f.next()
返回下一行或引起stopIteration,python3中,對應方法f.__next__()
In [1]: f=open('abc.txt','r+')   #打開文件,讀寫模式
In [3]: f.tell()                 #查看當前指針
Out[3]: 0
In [4]: f.read()                 #讀取文件,默認所有讀取
Out[4]: "Beautiful is better than ugly.\nExplicit is better than implicit.\nSimple is better than complex.\nComplex is better than complicated.\nFlat is better than nested.\nSparse is better than dense.\nReadability counts.\nSpecial cases aren't special enough to break the rules.\nAlthough practicality beats purity.\nErrors should never pass silently.\nUnless explicitly silenced.\nIn the face of ambiguity, refuse the temptation to guess.\nThere should be one-- and preferably only one --obvious way to do it.\nAlthough that way may not be obvious at first unless you're Dutch.\nNow is better than never.\nAlthough never is often better than *right* now.\nIf the implementation is hard to explain, it's a bad idea.\nIf the implementation is easy to explain, it may be a good idea.\nNamespaces are one honking great idea -- let's do more of those!\n"
In [5]: f.tell()                 #查看當前指針
Out[5]: 823
In [6]: f.seek(0)                #將指針移到開始處
Out[6]: 0
In [7]: f.readline()             #讀取單行文件
Out[7]: 'Beautiful is better than ugly.\n'
In [11]: f.readlines()           #讀取全部行返回列表
Out[11]: 
['Flat is better than nested.\n',
 'Sparse is better than dense.\n',
 'Readability counts.\n',
 "Special cases aren't special enough to break the rules.\n",
 'Although practicality beats purity.\n',
 'Errors should never pass silently.\n',
 'Unless explicitly silenced.\n',
 'In the face of ambiguity, refuse the temptation to guess.\n',
 'There should be one-- and preferably only one --obvious way to do it.\n',
 "Although that way may not be obvious at first unless you're Dutch.\n",
 'Now is better than never.\n',
 'Although never is often better than *right* now.\n',
 "If the implementation is hard to explain, it's a bad idea.\n",
 'If the implementation is easy to explain, it may be a good idea.\n',
 "Namespaces are one honking great idea -- let's do more of those!\n"]
In [33]: f.seek(0)
Out[33]: 0
In [34]: f.write('ksfdhauy3urnncb')  #寫入字符串 
Out[34]: 15
In [35]: f.close()                   #關閉文件
In [36]: f=open('abc.txt','r+')      #再次打開文件查看
In [37]: f.readline() 
Out[37]: 'ksfdhauy3urnncbtter than ugly.\n' #以讀寫模式打開時寫入的文件灰覆蓋已有的
In [39]: f=open('abc.txt','a')       #追加模式打開文件
In [40]: f.tell()                    #偏移指針直接在末尾處
Out[40]: 835
In [41]: f.write('5671528956knkxb')  #寫入文件
Out[41]: 15
In [47]: f.read()                    #查看文件,追加字符卸載了文件末尾處
Out[47]: "btter than ugly.\nExplicit is better than implicit.\nSimple is better than complex.\nComplex is better than complicated.\nFlat is better than nested.\nSparse is better than dense.\nReadability counts.\nSpecial cases aren't special enough to break the rules.\nAlthough practicality beats purity.\nErrors should never pass silently.\nUnless explicitly silenced.\nIn the face of ambiguity, refuse the temptation to guess.\nThere should be one-- and preferably only one --obvious way to do it.\nAlthough that way may not be obvious at first unless you're Dutch.\nNow is better than never.\nAlthough never is often better than *right* now.\nIf the implementation is hard to explain, it's a bad idea.\nIf the implementation is easy to explain, it may be a good idea.\nNamespaces are one honking great idea -- let's do more of those!\nhello world\n5671528956knkxb"

使用with自動關閉文件:

  當打開文件進行操做後忘記關閉時,在該文件對象再也不被引用後python會關掉此文件。這意味着在一個函數中打開文件,沒有及時關閉它,函數結束時會被關閉。可是當一直運行中的函數或者程序的主要部分打開一個文件,應該強制剩下的全部寫操做完成後才關閉文件。

  python的上下文管理器會清理一些資源,例如打開文件。形式爲:with context as varstatements

In [49]: with open('abc.txt','r+') as f:
    ...:     'akhkahga'      #寫入字符
    ...:     'fasfqwyqi'

  完成代碼編輯後文件自動關閉。

In [51]: with open('abc.txt','r+') as f:
    ...:     print(f.readline())   #讀取上次寫入的字符
    ...:     
ksfdhauy3urnncbtter than ugly.

2、對象流式化與持久化存儲

  Python 程序在實現文件讀取或寫出時,要使用轉換工具把對象轉換成字符串。持久性的基本思想很簡單,假定有一個Python 程序,它多是一個管理平常待辦事項的程序,你但願在屢次執行這個程序之間能夠保存應用程序對象,此時就須要持久存儲對象內容。python中只要有三個模塊用於流式化或持久化存儲數據:

  json, 用於字符串和python數據類型間進行轉換

  pickle 模塊 (將對象轉換爲文件存儲),讀寫文件時應使用二進制打開

  shelve 模塊(自動將對象pickle進和pickle出鍵轉換爲文件系統,按字典方式查詢方式)

  pickle、Json 模塊提供了四個功能:dumps、dump、loads、load,而shelve模塊經過open函數打開shelve對象後,就能夠至關於字典同樣操做。

dump(object, file)  dumps(object) -> string
將對象obj保存到文件file中去。    
load(file) -> object loads(string) -> object
從 file 中讀取一個字符串,並將它重構爲原來的python對象。
shelve模塊 d = shelve.open(filename) # 打開文件,d 至關於字典對象
In [53]: b={'a':123,'b':456,'c':123457}
In [54]: import json
In [56]: json_abc=json.dumps(b)  #將b轉換爲json所能識別的字符碼
In [58]: f=open('123.txt','w+')  #打開文件
In [59]: json.dump(json_abc,f)   #存入文件
In [60]: f.close()    
In [61]: cat 123.txt             #查看在文件中存儲的格式
"{\"a\": 123, \"b\": 456, \"c\": 123457}" 
In [63]: f=open('123.txt','r+')
In [64]: json_b=json.load(f)     #從文件中讀取字符串
In [65]: print(json_b)
{"a": 123, "b": 456, "c": 123457}


In [80]: pickle_f=open('pickle_123.txt','wb+')  #打開文件,以二進制格式讀寫
In [81]: pickle.dump(b,pickle_f)                #直接存儲對象
In [83]: pickle_f.close()
In [84]: b
Out[84]: {'a': 123, 'b': 456, 'c': 123457}
In [86]: pickle_f=open('pickle_123.txt','rb+') #從文件中讀取數據
In [87]: pickle.load(pickle_f)
Out[87]: {'a': 123, 'b': 456, 'c': 123457}


In [4]: shelve_dic=shelve.open('test.txt')   #直接打開一個文件,進行操做
In [5]: shelve_dic['a']=[1,2,3,4,56,76]
In [6]: shelve_dic['b']=[2,3,4,6,8]
In [7]: shelve_dic.close()
In [8]: ls                        #關閉shelve對象後,當前目錄下生成一個'test.txtx.bd'文件
123.txt  mylinux/        python_web/  shell/
abc.txt  pickle_123.txt  samba/       test.txt.db
In [9]: shelve_dic=shelve.open('test.txt')    #打開文件,能夠直接進行操做
In [18]: shelve_dic['a']
Out[18]: [1, 2, 3, 4, 56, 76]
In [19]: shelve_dic['b']
Out[19]: [2, 3, 4, 6, 8]
In [20]: shelve_dic['c']

       3、正則處理re模塊

  python中正則表達式的處理使用re模塊。其主要方法有:


search(pattern, string, flags=0)

根據patter模式,在string字符串中返回第一次匹配到的

match對象。

符號標誌:

  I或IGNORECASE:忽略字符大小寫

  M或MULTILINE:跨行匹配
  A或 ASCII:僅執行8位ASCII碼匹配 

  U或UNICODE:執行UNICODE 碼匹配

match(pattern, string, flags=0)

根據pattern匹配,返回一個match對象,只能檢測字符串做爲開頭的源字符串。

match對象的屬性:

  string: 匹配的源字符串

  re:     須要匹配的pattern

  pos:    源字符串搜索的起始位置

  endpos: 源字符串搜索的結束位置

match對象的方法: 

  group(): 匹配到的結果 

  groups():匹配到的分組結果以元組形式返回。

  start(): 匹配到字符串的起始位置

  end():   匹配到字符串的結束位置

findall(pattern, string, flags=0) 以列表的方式,返回全部不重複的匹配對象
sub(pattern, repl, string, count=0, flags=0) 返回替換後整個串
subn(pattern, repl, string, count=0, flags=0) 返回元組替換後的串及替換次數
compile(pattern, flags=0) 手動編譯模式對象,將正則表達式編譯成Pattern對象

split(string[, maxsplit]) 

split(pattern, string[,maxsplit])

按照可以匹配的子串將string分割後返回列表。

maxsplit用於指定最大分割次數,不指定將所有分割

In [11]: import re
In [12]: str
Out[12]: 'Beautiful is better than ugly.'
In [13]: ret=re.match('is',str)   #使用match()方法匹配is ,沒有返回結果
In [14]: ret
In [15]: ret=re.match('Bea',str)  #匹配字符串開頭出現結果,只能匹配字符串的開頭
In [16]: ret
Out[16]: <_sre.SRE_Match object; span=(0, 3), match='Bea'>
In [17]: ret.string                #匹配的源字符串
Out[17]: 'Beautiful is better than ugly.'
In [18]: ret.re                    #匹配的模式,須要匹配的內容
Out[18]: re.compile(r'Bea', re.UNICODE)
In [19]: ret.pos                    #源字符串搜索的起始位置                  
Out[19]: 0
In [20]: ret.endpos                 #源字符串搜索的結束位置
Out[20]: 30
In [22]: ret.group()                #匹配到的結果
Out[22]: 'Bea'
In [23]: ret.groups()               #沒有分組,所以爲空
Out[23]: ()
In [24]: ret.start()                #匹配到的結果在源字符串中的起始位置
Out[24]: 0
In [25]: ret.end()                  #匹配到的結果在源字符串中的結束位置
Out[25]: 3
In [26]: ret=re.match('(Bea)',str)  #以分組的方式進行匹配
In [27]: ret.groups()               #返回的分組結果以元組的形式返回
Out[27]: ('Bea',)
In [31]: ret=re.search('is',str)    #使用search()方法進行匹配
In [32]: ret.group()                #返回結果,
Out[32]: 'is'
In [34]: pat=re.compile('ea')       #對須要匹配的模式進行先編譯
In [35]: ret=pat.search(str)        #對模式編譯後,在源字符串中查找匹配
In [36]: ret.group()                #匹配結果
Out[36]: 'ea'
In [38]: str
Out[38]: 'Beautiful is better than ugly.'
In [39]: re.findall('a',str)       #列表的形式返回全部匹配的結果
Out[39]: ['a', 'a']
In [40]: re.sub('eau','aaa',str)   #返回字符串替換後的結果
Out[40]: 'Baaatiful is better than ugly.'

正則匹配規則:

語法 說明 表達式實例 完整匹配的規則
字符
. 匹配任意除換行符'\n'外的字符 a.b
aab
\ 轉義字符,使後一個字符改變原來的意思 a\.e a.e
[...] 字符集。對應的位置能夠是字符集中任意一個字符。 a[bc]d abd,acd
預約義字符集
\d 數字[0-9] a\db a1b
\D 非數字[^0-9] a\Db abb
\s 空白字符 a\sb a b
\S 非空白字符 a\Sb abb
\w 單詞字符[a-zA-Z0-9] a\wb abb,a1b,aWb
\W 非單詞字符 a\Wb a b,a-b,a*b
數量匹配
* 匹配前一個字符0次或屢次 ab* a,ab,abb
+ 匹配前一個字符1次或屢次 ab+ ab,abb
匹配前一個字符0次或1次 ab? a,ab
{m} 匹配前一個字符m次 ab{3}c abbbc
{m,n}
匹配前一個字符m至n次 ab{1,2}c abc,abbc
邊界匹配
^ 匹配字符串開頭 ^ab ab
$
匹配字符串結尾 ab$ ab
\A
僅匹配字符串開頭 \Aabc
abc
\Z
僅匹配字符串結尾 abc\Z abc
\b

匹配字符串邊界


cl\\b

ass\\b

'class'中cl沒法匹配;

'class'中ass能夠匹配

\B
不匹配字符串邊界

cl\B

ass\B

'class'中cl能夠匹配;

'class'中ass沒法匹配

邏輯與分組
| 左右表達式任意匹配一個 abc|abd abc,abd
(...) 如: \(ab\)*,ab 做爲一個總體匹配
\n: 後向引用, 引用前面的第 n 個左括號以及與之對應的右括號中的模式所匹配
到的內容

(abc){2}

a(123|456)c

abcabc

a123c,a456c

(?P<name>...) 分組,除了原有的編號外,再指定一個額外的別名 (?P<id>abc)2 abcabc
\<number> 引用編號爲<number>的分組匹配到的字符串 (\d)abc\1

5abc5

2abc2

(?=name) 引用別名爲name匹配到的字符串 (?P<id>\d)abc(?P=id)

5abc5

2abc2