python学习_python怎么读写文件操作

python学习_python怎么读写文件操作

本节内容:


  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+均可以完成对于文件的读写,那末他们有甚么差别呢?

[/wm_notice]

  • r+会掩盖以后文件指针地点地位的字符,如本来文件内容是"Hello,World",翻开文件后写入"hi"则文件内容会酿成"hillo, World"

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

  • a+与r+的差别是,a+只能写到文件开端(不管以后文件指针正在那里)

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

[/wm_notice]

对于这个成绩,我查了良多材料,也没找到很威望的说明。正在跟同业冤家交换进程中,发明大师次要有两种观念:

  • 跟平安无关,有这类观念的年夜局部是做运维的冤家,他们以为这就像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语句会帮咱们主动处置非常信息吗?

[/wm_notice]

要答复这个成绩就要提到“高低文办理器” 以及 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个汉字。

[/wm_notice]

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

输入后果:

仓促那年咱们 终究说

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

[/wm_notice]

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中字符串与字符编码的干系和转换进程。此中谈到过两个指定的字符编码之处,及其感化:

python学习_python怎么读写文件操作

  • 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怎样读写文件操纵的具体内容,更多请存眷酷吧易资源网别的相关文章!

收藏 (0) 打赏

感谢您的支持,我会继续努力的!

打开微信/支付宝扫一扫,即可进行扫码打赏哦,分享从这里开始,精彩与您同在
点赞 (0)

酷吧易资源网 python教程 python学习_python怎么读写文件操作 https://www.kubayi.com/4954.html

常见问题

相关文章

评论
暂无评论