python怎么读写文件操作-Python教程

资源魔 14 0

本节内容:


  1. I/O操作概述

  2. 文件读写完成原理与操作步骤

  3. 文件关上模式

  4. Python文件操作步骤示例

  5. Python文件读取相干办法

  6. 文件读写与字符编码

1、I/O操作概述


I/O正在较量争论机中是指Input/Output,也就是Stream(流)的输出以及输入。这里的输出以及输入是绝对于内存来讲的,Input Stream(输出流)是指数据从外(磁盘、网络)流进内存,Output Stream是数据从内存流出到里面(磁盘、网络)。顺序运转时,数据都是正在内存中驻留,由CPU这个超快的较量争论外围来执行,触及到数据替换之处(一般为磁盘、网络操作)就需求IO接口。

那末这个IO接口是由谁提供呢?初级编程言语中的IO操作是若何完成的呢?

操作零碎是个通用的软件顺序,其通用目的以下:

  • 硬件驱动

  • 过程治理

  • 内存治理

  • 网络治理

  • 平安治理

  • I/O治理

操作零碎屏蔽了底层硬件,向上提供通用接口。因而,操作I/O的才能是由操作零碎的提供的,每一一种编程言语城市把操作零碎提供的低级C接口封装起来供开发者应用,Python也没有破例。

2、文件读写完成原理与操作步骤


1. 文件读写完成原理

文件读写就是一种常见的IO操作。那末依据下面的形容,能够揣度python也应该封装操作零碎的底层接口,间接提供了文件读写相干的操作办法。现实上,也的确如斯,并且Java、PHP等其余言语也是。

那末咱们要操作的工具是甚么呢?咱们又若何猎取要操作的工具呢?

因为操作I/O的才能是由操作零碎提供的,且古代操作零碎没有容许一般顺序间接操作磁盘,以是读写文件时需求申请操作零碎关上一个工具(通常被称为文件形容符--file descriptor, 简称fd),这就是咱们正在顺序中要操作的文件工具。

通常初级编程言语中会提供一个内置的函数,经过接纳"文件门路"和“文件关上模式”等参数来关上一个文件工具,并前往该文件工具的文件形容符。因而经过这个函数咱们就能够猎取要操作的文件工具了。这个内置函数正在Python中叫open(), 正在PHP中叫fopen(),

2. 文件读写操作步骤

没有同的编程言语读写文件的操作步骤大要都是同样的,都分为如下几个步骤:

1)关上文件,猎取文件形容符2)操作文件形容符--读/写3)封闭文件

只是没有同的编程言语提供的读写文件的api是纷歧样的,有些提供的性能比拟丰厚,有些比拟粗陋。

需求留意的是:文件读写操作实现后,应该实时封闭。一方面,文件工具会占用操作零碎的资本;另一方面,操作零碎对同一工夫能关上的文件形容符的数目是无限制的,正在Linux操作零碎上能够经过ulimit -n 来查看这个显示数目。假如不迭时封闭文件,还可能会造成数据失落。由于我将数据写入文件时,操作零碎没有会立即把数据写入磁盘,而是先把数据放到内存缓冲区异步写入磁盘。当挪用close办法时,操作零碎会保障把不写入磁盘的数据全副写到磁盘上,不然可能会失落数据。

3、文件关上模式


咱们先来看下正在Python、PHP以及C言语中关上文件的函数界说

Python
# Python2open(name[, mode[, buffering]])# Python3open(file, mode='r', buffering=-1, encoding=None, errors=None, newline=None, closefd=True, opener=None)
PHP
resource fopen ( string $filename , string $mode [, bool $use_include_path = false [, resource $context ]] )
C言语
int open(const char * pathname, int flags);

会发现以上3种编程言语内置的关上文件的办法接纳的参数中,除了了都蕴含一个“文件门路称号”,还会蕴含一个mode参数(C言语的open函数中的flags参数作用类似)。这么mode参数界说的是关上文件时的模式,常见的文件关上模式有:只读、只写、可读可写、只追加。没有同的编程言语中对文件关上模式的界说有些巨大的差异,咱们来看下Python中的文件关上模式有哪些。

文件关上模式形容
r以只读模式关上文件,并将文件指针指向文件头;假如文件没有存正在会报错
w以只写模式关上文件,并将文件指针指向文件头;假如文件存正在则将其内容清空,假如文件没有存正在则创立
a以只追加可写模式关上文件,并将文件指针指向文件尾部;假如文件没有存正在则创立
r+正在r的根底上添加了可写性能
w+正在w的根底上添加了可读性能
a+正在a的根底上添加了可读性能
b读写二进制文件(默许是t,示意文本),需求与下面几种模式搭配应用,如ab,wb, ab, ab+(POSIX零碎,包罗Linux城市疏忽该字符)

考虑1: r+、w+以及a+均可以完成对文件的读写,那末他们有甚么区分呢?

  • r+会笼罩以后文件指针所正在地位的字符,如原来文件内容是"Hello,World",关上文件后写入"hi"则文件内容会变为"hillo, World"

  • w+与r+的没有同是,w+正在关上文件时就会先将文件内容清空,没有晓得它有甚么用

  • a+与r+的没有同是,a+只能写到文件末尾(无论以后文件指针正在那里)

考虑2: 为何要界说这些模式呢?为何不克不及像咱们用word关上一篇文档同样既能够读,又能够写,还可修正呢?

对于这个成绩,我查了不少材料,也没找到很权势巨子的阐明。正在跟偕行冤家交流进程中,发现各人次要有两种观念:

  • 跟平安无关,有这类观念的年夜局部是做运维的冤家,他们以为这就像linux上的rwx(读、写、执行)权限。

  • 跟操作零碎内核治理I/O的机制无关,有这类观念的年夜局部是做C开发的,特地是与内核相干的开发职员。为了进步读写速率,要写入磁盘的数据会先放进内存缓冲区,之后再回写。因为可能会同时关上不少文件,当要回写数据时,需求遍历以关上的文件判别能否需求回写。他们以为假如关上文件时指定了读写模式,那末需求回写时,只需去查找以“可写模式”关上的文件就能够了。

4、Python文件操作步骤示例


咱们来读取这样一个文本文件:song.txt,该文件的字符编码为utf-8。

促那年咱们 终究说了几遍 再会之后再迟延
惋惜谁有无 爱过没有是一场 七情下面的雄辩
促那年咱们 一时匆仓促撂下 难以接受的诺言
只有等他人兑现

1. 菜鸟完成(只是完成性能):

Python3完成:

# 第一步:(以只读模式)关上文件f = open('song.txt', 'r', encoding='utf-8')# 第二步:读取文件内容print(f.read())# 第三步:封闭文件f.close()

这里说下Python2的完成

# 第一步:(以只读模式)关上文件f = open('song.txt', 'r')# 第二步:读取文件内容print(f.read().decode('utf-8'))# 第三步:封闭文件f.close()

阐明:
Python3中曾经内置对Unicode的支持,字符串str曾经是真实的Unicode字符串。也就是说Python3中的文件读取办法曾经主动实现理解码解决,因而无需再手动进行解码,能够间接将读取的文件中的内容进行打印;Python2中的字符串str是字节串,读取文件失去的也是字节串,正在打印以前应该手动将其解码成Unicode字符串。对于这局部的阐明,能够参考以前这篇文章<<再谈Python中的字符串与字符编码>>。

2. 中级完成

正在完成根本性能的条件下,思考一些可能的不测要素。由于文件读写时都有可能孕育发生IO谬误(IOError),一旦犯错,前面包罗f.close()正在内的一切代码都没有会执行了。因而咱们要保障文件无论若何都能被封闭。那末能够用try...finally来完成,这实际上就是try...except..finally的简化版(咱们只用Python3来进行示例演示):

f = ''try:
    f = open('song.txt', 'r', encoding='utf-8')    print(f.read())
    num = 10 / 0finally:    print('>>>>>>finally')    if f:
        f.close()

输入后果:

促那年咱们 终究说了几遍 再会之后再迟延
惋惜谁有无 爱过没有是一场 七情下面的雄辩
促那年咱们 一时匆仓促撂下 难以接受的诺言
只有等他人兑现>>>>>>finally
Traceback (most recent call last):
  File "<stdin>", line 4, in <module>ZeroDivisionError: division by zero

输入后果阐明,虽然with代码块中呈现了异样,然而”>>>>>>finally“ 信息仍是被打印了,阐明finally代码块被执行,即文件封闭操作被执行。然而后果中谬误信息仍是被输入了,因而仍是倡议用一个实现的try...except...finally语句对异样信息进行捕捉以及解决。

3. 最好理论

为了不遗记或许为了不每一次都要手动封闭文件,咱们能够应用with语句(一种语法糖,语法糖语句一般为为了简化某些操作而设计的)。with语句会正在其代码块执行终了之后主动封闭文件。因而咱们能够这样来改写下面的顺序:

with open('song.txt', 'r', encoding='utf-8') as f:    print(f.read())print(f.closed)

输入后果:

促那年咱们 终究说了几遍 再会之后再迟延惋惜谁有无 爱过没有是一场 七情下面的雄辩促那年咱们 一时匆仓促撂下 难以接受的诺言只有等他人兑现True

是否是变患上简介多了,代码构造也比拟明晰了。with之后打印的f.closed属性值为True,阐明文件的确被封闭了。

考虑:
with语句会帮咱们主动解决异样信息吗?

要答复这个成绩就要提到“上下文治理器” 以及 with语句的工作流程。

with语句不只仅能够用于文件操作,它其实是一个很通用的构造,容许应用所谓的上下文治理器(context manager)。上下文治理器是一种支持__enter__()以及__exit__()这两个办法的工具。__enter__()办法没有带任何参数,它正在进入with语句块的时分被挪用,该办法的前往值会被赋值给as要害字之后的变量。__exit__()办法带有3个参数:type(异样类型), value(异样信息), trace(异样栈),当with语句的代码块执行终了或执行进程中由于异样而被终止城市挪用__exit__()办法。失常加入时该办法的3个参数都为None,异样加入时该办法的3个参数会被辨别赋值。假如__exit__()办法前往值(真值测试后果)为True则示意异样曾经被解决,饬令执行后果中就没有会抛出异样信息了;反之,假如__exit__()办法前往值(真值测试后果)为False,则示意异样不被解决而且会向外抛出该异样。

如今咱们应该明确了,异样信息会没有会被解决是由with后的语句前往工具的__exit__()办法决议的。文件能够被用作上下文治理器。它的__enter__办法前往文件工具自身,__exit__办法会封闭文件并前往None。咱们看下file类中对于这两个办法的完成:

def __enter__(self): # real signature unknown; restored from __doc__
    """ __enter__() -> self. """
    return self    
def __exit__(self, *excinfo): # real signature unknown; restored from __doc__
    """ __exit__(*excinfo) -> None.  Closes the file. """
    pass

可见,file类的__exit__()办法的前往值为None,None的真值测试后果为False,因而用于文件读写的with语句代码块中的异样信息仍是会被抛进去,需求咱们本人去捕捉并解决。

with open('song.txt', 'r', encoding='utf-8') as f:    print(f.read())    num = 10 / 0

输入后果:

促那年咱们 终究说了几遍 再会之后再迟延
惋惜谁有无 爱过没有是一场 七情下面的雄辩
促那年咱们 一时匆仓促撂下 难以接受的诺言
只有等他人兑现
Traceback (most recent call last):  File "<stdin>", line 3, in <module>
ZeroDivisionError: division by zero

留意: 下面所说的__exit__()办法前往值(真值测试后果)为True则示意异样曾经被解决,指的是with代码块中呈现的异样。它关于with要害字之后的代码中呈现的异样是没有起作用的,由于尚未进入上下文治理器就曾经发作异样了。因而,无论若何,仍是倡议正在须要的时分正在with语句里面套上一层try...except来捕捉以及解决异样。

无关“上下文治理器”这个弱小且初级的特点的更多信息,请参看Python参考手册中的上下文治理器局部。或许能够正在Python库参考中查看上下文治理器以及contextlib局部。

5、Python文件读取相干办法


咱们晓得,对文件的读取操作需求将文件中的数据加载到内存中,而下面所用到的read()办法会一次性把文件中一切的内容全副加载到内存中。这显著是没有正当的,当遇到一个几个G的的文件时,必定会耗光机械的内存。这里咱们来引见下Python中读取文件的相干办法:

办法形容
read()一次读取文件一切内容,前往一个str
read(size)每一次最多读取指定长度的内容,前往一个str;正在Python2中size指定的是字节长度,正在Python3中size指定的是字符长度
readlines()一次读取文件一切内容,按行前往一个list
readline()每一次只读取一行内容

别的,还要两个与文件指针地位相干的办法

办法形容
seek(n)将文件指针挪动到指定字节的地位
tell()猎取以后文件指针所正在字节地位

上面来看下操作实例

1. 读取指定长度的内容

Python2
with open('song.txt', 'r') as f:    print(f.read(12).decode('utf-8'))

输入后果:

促那年

后果阐明:Python2中read(size)办法的size参数指定的要读取的字节数,而song.txt文件是UTF-8编码的内容,一个汉字占3个字节,因而12个字节刚好是4个汉字。

Python3
with open('song.txt', 'r', encoding='utf-8') as f:    print(f.read(12))

输入后果:

促那年咱们 终究说

后果阐明:Python3中read(size)办法的size参数指定的要读取的字符数,这与文件的字符编码有关,就是前往12个字符。

2. 读取文件中的一行内容

Python2
with open('song.txt', 'r', encoding='utf-8') as f:    print(f.readline())
Python3
with open('song.txt', 'r') as f:    print(f.readline().decode('utf-8'))

输入后果都同样:

促那年咱们 终究说了几遍 再会之后再迟延

3. 遍历打印一个文件中的每一一行

这里咱们只以Python3来进行实例操作,Python2仅仅是需求正在读取到内容落后行手动解码罢了,下面曾经有示例。

形式一:先一次性读取一切行到内存,而后再遍历打印

with open('song.txt', 'r', encoding='utf-8') as f:    for line in f.readlines():
        print(line)

输入后果:

促那年咱们 终究说了几遍 再会之后再迟延

惋惜谁有无 爱过没有是一场 七情下面的雄辩

促那年咱们 一时匆仓促撂下 难以接受的诺言

只有等他人兑现

这类形式的缺陷与read()办法是同样的,都是会耗费年夜量的内存空间。

形式二:经过迭代器一行一行的读取并打印

with open('song.txt', 'r', encoding='utf-8', newline='') as f:
    for line in f:
        print(line)

输入后果:

促那年咱们 终究说了几遍 再会之后再迟延

惋惜谁有无 爱过没有是一场 七情下面的雄辩

促那年咱们 一时匆仓促撂下 难以接受的诺言

只有等他人兑现

另外,发现下面的输入后果中行与行之间多了一个空行。这是由于文件每一一行的默许都有换行符,而print()办法也会输入换行,因而就多了一个空行。去掉空行也比拟简略:能够用line.rstrip()去除了字符串左边的换行符,也能够经过print(line, end='')防止print办法酿成的换行。

file类的其余办法:

办法形容
flush()刷新缓冲区数据,将缓冲区中的数据立即写入文件
next()前往文件下一行,这个办法也是file工具实例能够被当作迭代器应用的缘由
truncate([size])截取文件中指定字节数的内容,并笼罩保留到文件中,假如没有指定size参数则文件将被清空; Python2无前往值,Python3前往新文件的内容字节数
write(str)将字符串写入文件,不前往值
writelines(sequence)向文件写入一个字符串或一个字符串列表,假如字符串列表中的元素需求换行要本人退出换行符
fileno()前往一个整型的文件形容符,能够用于一些底层IO操作上(如,os模块的read办法)
isatty()判别文件能否被衔接到一个虚构终端,是则前往True,不然前往False

6、文件读写与字符编码


后面曾经写过一篇引见Python中字符编码的相干文件<<再谈Python中的字符串与字符编码>> 外面花了很年夜的篇幅引见Python中字符串与字符编码的关系和转换进程。此中谈到过两个指定的字符编码之处,及其作用:

1063221-20161213112530354-979116962.png

  • PyCharm等IDE开发对象指定的名目工程以及文件的字符编码: 它的次要作用是通知Pycharm等IDE开发对象保留文件时应该将字符转换为怎么的字节示意方式,和关上并展现文件内容时应该以甚么字符编码将字节码转换为人类可辨认的字符。

  • Python源代码文件头部指定的字符编码,如*-* coding:utf-8 -*- 它的次要作用是通知Python诠释器以后python代码文件保留时所应用的字符编码,Python诠释器正在执行代码以前,需求先从磁盘读取该代码文件中的字节而后经过这里指定的字符编码将其解码为unicode字符。Python诠释器执行Python代码的进程与IDE开发对象是不甚么联系关系性的。

那末这里为何又要谈起字符编码的成绩呢?

或许换个问法,既然从下面曾经指定了字符编码,为何对文件进行读写时还要指定字符编码呢?畴前面的形容能够看出:下面两个中央指定的是Python代码文件的字符编码,是给Python诠释器以及Pycharm等顺序软件用的;而被读写文件的字符编码与Python代码文件的字符编码不必定联络,读写文件时指定的字符编码是给咱们写的顺序软件用的。这是没有同的主体以及进程,心愿我阐明白了。

读写文件时怎么指定字符编码呢?

下面诠释了读写文件为何要指定字符编码,这里要说下怎么指定字符编码(其实这里次要探讨是读取内部数据时的情景)。这个成绩其真实下面的文件读取示例中曾经应用过了,这里咱们再具体的说一下。

起首,再次看一下Python2以及Python3中open函数的界说:

# Python2open(name[, mode[, buffering]])# Python3open(file, mode='r', buffering=-1, encoding=None, errors=None, newline=None, closefd=True, opener=None)

能够看到,Python3的open函数中多了几个参数,此中包罗一个encoding参数。是的,这个encoding就是用来指定被操作文件的字符编码的。

# 读操作with open('song.txt', 'r', encoding='utf-8') as f:
    print(f.read())# 写操作with open('song.txt', 'w', encoding='utf-8') as f:
    print(f.write('你好'))

那末Python2中怎么指定呢?Python2中的对文件的read以及write操作都是字节,也就说Python2中文件的read相干办法读取的是字节串(假如蕴含中文字符,会发现len()办法的后果没有等于读取到的字符个数,而是字节数)。假如咱们要失去 正确的字符串,需求手动将读取到的后果decode(解码)为字符串;相同,要以特定的字符编码保留要写入的数据时,需求手动encode(编码)为字节串。这个encode()以及decode()函数能够接纳一个字符编码参数。Python3中read以及write操作的都是字符串,其实是Python诠释器帮咱们主动实现了写入时的encode(编码)以及读取时的decode(解码)操作,因而咱们只要要正在关上文件(open函数)时指定字符编码就能够了。

# 读操作with open('song.txt', 'r') as f:
     print(f.read().decode('utf-8'))

# 写操作with open('song2.txt', 'w') as f:
    # f.write(u'你好'.encode('utf-8'))
    # f.write('你好'.decode('utf-8').encode('utf-8'))
    f.write('你好')
文件读写时有无默许编码呢?

Python3中open函数的encoding参数显然是能够没有指定的,这时候候就会用一个“默许字符编码”。
看下Python3中open函数文档对encoding参数的阐明:

encoding is the name of the encoding used to decode or encode thefile. This should only be used in text mode. The default encoding isplatform dependent, but any encoding supported by Python can be
passed.  See the codecs module for the list of supported encodings.

也就是说,encoding参数的默许值是与平台无关的,比方Window上默许字符编码为GBK,Linux上默许字符编码为UTF-8。

而关于Python2来讲,正在进行文件写操作时,字节会被间接保留;正在进行文件读操作时,假如没有手动进行来decode操作天然也就用没有着默许字符编码了。然而这时候候正在没有同的字符终端打印的时分,会用以后平台的字符编码主动将字节解码为字符,此时可能会呈现乱码。如song.txt文件时UTF-8编码的,正在windows(字符编码为GBK)的饬令行终端进行以下操作就会呈现乱码:

>>> with open('song.txt', 'r') as f:
...     print(f.read())
...
鍖嗗寙閭e勾鎴戜滑 绌剁珶璇翠簡鍑犻亶 鍐嶈涔嬪悗鍐嶆嫋寤?
鍙儨璋佹湁娌℃湁 鐖辫繃涓嶆槸涓€鍦?涓冩儏涓婇潰鐨勯泟杈?
鍖嗗寙閭e勾鎴戜滑 涓€鏃跺寙蹇欐拏涓?闅句互鎵垮彈鐨勮瑷€
鍙湁绛夊埆浜哄厬鐜

咱们应该尽可能的猎取被操作文件的字符编码,并明白指定encoding参数的值。

相干教程保举:Python视频教程

以上就是python怎样读写文件操作的具体内容,更多请存眷资源魔其它相干文章!

标签: Python python教程 python编程 python使用问题 读写文件

抱歉,评论功能暂时关闭!