Python学习(四)

学习网址:廖雪峰的Python教程

IO编程

文件读写取

在磁盘上读写文件的功能都是由操作系统提供的,现代操作系统不允许一般的程序直接操作磁盘,读写文件就是请求操作系统打开一个文件对象,然后通过操作系统提供的接口从这个文件对象中读取数据(读文件),或者把数据写入文件对象(写文件).

使用Python内置的open()函数,传入文件路径名和标示符,就能打开一个文件,如果文件不存在,会抛出一个IOError,并指出错误出现的地方:

1
2
3
4
>>> f=open('/Users/michael/notfound.txt', 'r')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>FileNotFoundError:
[Errno 2] No such file or directory: '/Users/michael/notfound.txt'

r,表示读取,如果打开成功,read()方法可以读取文件的全部内容,把内容读到内存,用str对象表示,最后要调用close()方法来关闭读取操作,这一步必须有,很重要.

在文件读写的过程中,都有可能发生IOError,后面的close()方法就不会执行了,Python内置的有with语句自动帮我们自动调用close()方法:

1
2
with open('/path/to/file', 'r') as f:
print(f.read())

read()方法可以读取目标文件的全部内容,这不太保险,如果文件过大,内存容量不够,就挂掉了,如果文件很小的话,这个很方便.

read(size)方法可以每次读取多少字节,在不确定文件大小的情况下,反复调用read(size)方法最保险.

readline()可以读取一行.

readlines()可以读取所有行的内容并按行返回list. 如果是配置文件,这个很方便.

按照需求,选取合适的方法.

二进制文件的读取,如图片,视频,用’rb‘模式打开:

1
2
3
>>> f = open('/Users/michael/test.jpg', 'rb')
>>> f.read()
b'\xff\xd8\xff\xe1\x00\x18Exif\x00\x00...' # 十六进制表示的字节

想要读取特定编码的文件对象,需要在open()函数中传入编码类型encoding:

1
2
3
>>> f = open('/Users/michael/gbk.txt', 'r', encoding='gbk')
>>> f.read()
'测试'

如遇到编码不规范的文件,可能会有UnicodeDecodeError.

文件中可能含有非法字符,在open()函数中黑可以传入一个errors参数,表示如果遇到异常如何处理,

1
>>> f = open('/Users/michael/gbk.txt', 'r', encoding='gbk', errors='ignore')
文件写入

文件写入和文件读取类似,只不过在open()函数中的参数是’w’和’wb’,用来读取文本文件和二进制文件

1
2
3
>>> f = open('/Users/michael/test.txt', 'w')
>>> f.write('Hello, world!')
>>> f.close()

用with语句最保险:

1
2
with open('/Users/michael/test.txt', 'w') as f:
f.write('Hello, world!')

反复调用write()方法,最重要的是还要调用close()方法,这样才能保证,系统把数据全部写入到指定文件中,如果要指定编码类型,只需要在open()函数中传入指定的的编码就可以了.

StringIO

是在内存中读写str:

1
2
3
4
5
6
7
8
9
10
>>> from io import StringIO
>>> f = StringIO()
>>> f.write('hello')
5 #字符个数
>>> f.write(' ')
1
>>> f.write('world!')
6
>>> print(f.getvalue())
hello world!

getvalue()是用于获取写入后的字符串.

读取StringIO和读取文件类似

1
2
3
4
5
6
7
8
9
10
11
>>> from io import StringIO
>>> f = StringIO('Hello!\nHi!\nGoodbye!')
>>> while True:
... s = f.readline()
... if s == '':
... break
... print(s.strip())
...
Hello!
Hi!
Goodbye!
BytesIO

用于读写二进制数据.

1
2
3
4
5
>>> from io import BytesIO
>>> f = BytesIO()
>>> f.write('中文'.encode('utf-8'))6
>>> print(f.getvalue())
b'\xe4\xb8\xad\xe6\x96\x87'

用BytesIO写入的不是str,而是经过编码后的byte字节,读取类似StringIO,先获得BytesIO的对象,进行读取:

1
2
3
4
>>> from io import BytesIO
>>> f = BytesIO(b'\xe4\xb8\xad\xe6\x96\x87')
>>> f.read()
b'\xe4\xb8\xad\xe6\x96\x87'
操作文件和目录

在Python中操作文件和目录的命令都在os模块和os.path模块当中

1
2
3
>>> import os
>>> os.name
'nt'

操作系统类型,nt 代表Windows,还有POSIX类型,代表Linux,Unix,或者MacOs.

环境变量:

1
>>> os.environ

取得某个环境变量的值:

1
>>> os.environ.get('path')

当前目录的绝对路径:

1
>>> os.path.abspath('.')

把两个路径合成一个时:

1
os.path.join()

拆分路径:

1
2
>>> os.path.split('C:/Users/snow/Desktop/22.txt')
('C:/Users/snow/Desktop', '22.txt')

拆分直接得到文件扩展名:

1
2
>>> os.path.splitext('C:/Users/snow/Desktop/22.txt')
('C:/Users/snow/Desktop/22', '.txt')

合并,拆分路径操作,并不要次文件真实存在,只是对字符串进行操作.

对文件重命名:

1
>>>os.rename('test.txt', 'test.py')

删掉文件:

1
>>>os.remove('test.py')

shutil模块中有copyfile()函数.

列出当前目录下的所有文件夹:

1
2
>>> [x for x in os.listdir('.') if os.path.isdir(x)]
['DLLs', 'Doc', 'include', 'Lib', 'libs', 'Scripts', 'tcl', 'Tools']

列出所有的.py文件:

1
2
3
>>> import os
>>> [x for x in os.listdir('.') if os.path.isfile(x) and os.path.splitext(x)[1]=='.py']
['break.py', 'if.py', 'learning.py', 'secret.py', 'sum.py', 'turtle.py']
序列化

把变量从内存中变成可存储或传输的过程称之为序列化,在Python中叫pickling,序列化之后,就可以把序列化后的内容写入磁盘,或者通过网络传输到别的机器上.

反过来,把序列化之后的对象读到内存中,称为反序列化,unpickling.

pickle模块

实现序列化:

1
2
3
4
>>> import pickle
>>> d = dict(name='Snow',age=20,score=88)
>>> pickle.dumps(d)
b'\x80\x03}q\x00(X\x04\x00\x00\x00nameq\x01X\x04\x00\x00\x00Snowq\x02X\x05\x00\x00\x00scoreq\x03KXX\x03\x00\x00\x00ageq\x04K\x14u.'

pickle.dumps()方法可以把任意对象序列化成一个bytes,然后,就可以把bytes写入文件,或者,用pickle.dump()直接把对象序列化后写入一个file-like-Object:

1
2
3
4
5
6
>>> import pickle
>>> d = dict(name='snow',age =22,sorce=90)
>>> f = open('33.txt','wb')
>>> pickle.dump(d,f)
>>> f.close
<built-in method close of _io.BufferedWriter object at 0x00000000011AA938>

33.txt中的内容像这样:

1
2
3
4
5
6
7
8003 7d71 0028 5803 0000 0061 6765 7101
4b16 5805 0000 0073 6f72 6365 7102 4b5a
5804 0000 006e 616d 6571 0358 0400 0000
736e 6f77 7104 752e 8003 7d71 0028 5803
0000 0061 6765 7101 4b16 5805 0000 0073
6f72 6365 7102 4b5a 5804 0000 006e 616d
6571 0358 0400 0000 736e 6f77 7104 752e

当把对象从磁盘中读到内存时候,可以先读取一个bytes,然后用pickle.loads()方法反序列化出对象,也可以用pickl.load()方法从一个file-like-Object中直接反序列化出对象,

1
2
3
4
5
>>> f = open('33.txt','rb')
>>> d = pickle.load(f)
>>> f.close()
>>> d
{'age': 22, 'sorce': 90, 'name': 'snow'}

pickle只能用于python,不同版本的互不兼容,只能用pickle存储一些不太重要的信息.

JSON

要在不同编程语言之间传递对象,就要把对象序列化为标准格式,JSON表示的是一个字符串,可以被所有语言读取,可以方便的存储到磁盘或者通过网络传输,可以直接在Web页面读取.

JSON类型 Python类型
{} dict
[] list
“string” str
1234.56 int或float
true/false True/False
null None

python对象转化为JSON:

1
2
3
4
>>> import json
>>> d = dict(name='snow',age =22,sorce=90)
>>> json.dumps(d)
'{"age": 22, "sorce": 90, "name": "snow"}'

使用JSON反序列化为Python对象,用loads(),或者load()方法,loads()方法将JSON的字符串反序列化,load()方法将从file-like-Object读取字符串并反序列化:

1
2
3
4
>>> import json
>>> json_str = '{"age": 22, "sorce": 90, "name": "snow"}'
>>> json.loads(json_str)
{'name': 'snow', 'age': 22, 'sorce': 90}

JSON标准规定JSON编码是UTF-8.

Python语言序列化的模块是pickle,想要把序列化更通用,更符合web标准,就可以用JSON.


真诚地希望能帮到你!