python 文件处理、数据持久化与正则

  1. 云栖社区>
  2. 博客>
  3. 正文

python 文件处理、数据持久化与正则

技术小阿哥 2017-11-27 14:37:00 浏览746
展开阅读全文

一、文件的处理

  数据持久化最简单的类型就是普通文件,有时也叫做平面文件(flat file)。文件是计算机中由OS(操作系统)管理的具有名字的存储区域,在linux系统上,文件被看作是字节序列。

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

  fileobj是open()函数返回的文件对象

  filename需要打开的文件的字符串名

  buffering:是否使用缓存,0表示输出无缓存,1表示使用缓存;

    负数表示使用默认设置,正数表示使用近似指定的大小。

  mode指定文件的打开模式:

    r表示读模式

    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__()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
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

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

  完成代码编辑后文件自动关闭。

1
2
3
4
In [51]: with open('abc.txt','r+') as f:
    ...:     print(f.readline())   #读取上次写入的字符
    ...:     
ksfdhauy3urnncbtter than ugly.

二、对象流式化与持久化存储

  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 相当于字典对象
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
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]: [12345676]
In [19]: shelve_dic['b']
Out[19]: [23468]
In [20]: shelve_dic['c']

       三、正则处理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用于指定最大分割次数,不指定将全部分割

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
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=(03), 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: 后向引用, 引用前面的第 个左括号以及与之对应的右括号中的模式所匹配
到的内容

(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




本文转自 梦想成大牛 51CTO博客,原文链接:http://blog.51cto.com/yinsuifeng/1906519,如需转载请自行联系原作者

网友评论

登录后评论
0/500
评论
技术小阿哥
+ 关注