中文部分转自:https://blog.csdn.net/qq_26591517/article/details/78764472
英文部分摘自: Python3, codecs官方文档
python读写文件估计大家都用open内置函数,或者file这个工厂函数,这两个的效果基本一样。
打开文件的方式一般为:f=open(file_name,access_mode = ‘r’,buffering = -1)。file_name就是文件的路径加文件名字,不加路径则文件会存放在python程序的路径下,
access_mode就是操作文件的模式,主要有r,w,rb,wb等,细节网上一大堆,buffering = -1是用于指示访问文件所采用的缓存方式。0表示不缓存;1表示只缓存一行,n代表缓存n行。如果不提供或为负数,则代表使用系统默认的缓存机制。
打开以后就是写和读的操作。但是用open方法打开会有一些问题。open打开文件只能写入str类型,不管字符串是什么编码方式。例如
>>> fr = open('test.txt','a')
>>> line1 ="我爱祖国"
>>> fr.write(line1)
这样是完全可以的。但是有时候我们爬虫或者其他方式得到一些数据写入文件时会有编码不统一的问题,所以就一般都统一转换为unicode。此时写入open方式打开的文件就有问题了。例如
>>> line2 =u'我爱祖国'
>>> fr.write(line2)
Traceback (most recent call last):
File""newfile", line1, in fr.write(line2) Unicode Encode Error: 'ascii' codec can't encode characters in position 0-11: ordinal not in range(128)
怎么办,我们可以将上面的line2编码成str类型,但是太麻烦。我们要把得到的东西先decode为unicode再encode为str。。。
input文件(gbk, utf-8…) —-decode—–> unicode ——-encode——> output文件(gbk, utf-8…)
代替这繁琐的操作就是codecs.open,例如
>>> import codecs
>>> fw = codecs.open('test1.txt','a','utf-8')
>>> fw.write(line2)
不会报错,说明写入成功。这种方法可以指定一个编码打开文件,使用这个方法打开的文件读取返回的将是unicode。写入时,如果参数 是unicode,则使用open()时指定的编码进行编码后写入;如果是str,则先根据源代码文件声明的字符编码,解码成unicode后再进行前述 操作。相对内置的open()来说,这个方法比较不容易在编码上出现问题。
注:
codecs.open() 的说明文档:
codecs.open(filename, mode='r', encoding=None, errors='strict', buffering=1)
Open an encoded file using the given mode and return an instance of StreamReaderWriter, providing transparent encoding/decoding. The default file mode is 'r', meaning to open the file in read mode.
Underlying encoded files are always opened in binary mode. No automatic conversion of '\n' is done on reading and writing. The mode argument may be any binary mode acceptable to the built-in open() function; the 'b' is automatically added.
encoding specifies the encoding which is to be used for the file. Any encoding that encodes to and decodes from bytes is allowed, and the data types supported by the file methods depend on the codec used.
errors may be given to define the error handling. It defaults to 'strict' which causes a ValueError to be raised in case an encoding error occurs. 【详细,见下】
buffering has the same meaning as for the built-in open() function. It defaults to line buffered.
注2:
The errors argument specifies the response when the input string can’t be converted according to the encoding’s rules. Legal values for this argument are 'strict' (raise a UnicodeDecodeError exception), 'replace' (useU+FFFD, REPLACEMENT CHARACTER), 'ignore' (just leave the character out of the Unicode result), or 'backslashreplace' (inserts a \xNN escape sequence). The following examples show the differences:
>>> b'\x80abc'.decode("utf-8","strict")
Traceback (most recent call last):...UnicodeDecodeError: 'utf-8' codec can't decode byte 0x80 in position 0: invalid start byte
>>> b'\x80abc'.decode("utf-8","replace")
'\ufffdabc'
>>> b'\x80abc'.decode("utf-8","backslashreplace")
'\\x80abc'
>>> b'\x80abc'.decode("utf-8","ignore")
'abc'