文件操作Python,python文件处理实例
Yyds干货库存
对我来说,在程序开始读取或写入外部文件之前,任何项目都不会感觉“真实”。
不幸的是,这是教程过于简化导致的最容易出现的问题之一。如果有人能在一个地方记录所有奇怪的事情就好了…
打开文件让我们从最基本的文件读取示例开始。假设在我的代码文件所在的目录中有一个名为journal1.txt的文件。
打开文件的标准方式是使用内置的open()函数,默认情况下是从io模块导入的。
file=open(journal1.txt , r )
对于文件中的行:
打印(行)
file.close() open()函数接受许多用于以高级方式与文件交互的参数,但是在大多数情况下,您只需要前两个参数。
第一个参数file接受一个包含打开文件的绝对或相对路径的字符串。这是唯一严格要求的参数。
第二个参数mode接受指示文件模式的字符串。如果未指定,将使用“rt”,这意味着它将文件作为文本读取。模式“r”实际上是相同的,因为文本模式(t)是默认行为的一部分。
我可以用这条线代替,得到同样的行为。
File=open(journal1.txt )但我个人更喜欢明确表示我是在读(R)、写(W),还是你有什么。
从open()返回的所有“文件”对象都是迭代的。对于文本文件,返回一个TextIOWrapper对象。在上面的例子中,我遍历了TextIOWrapper对象文件中的行,并打印出了每一行。
处理完文件后,我需要用file.close()关闭它。重要的是不要依赖垃圾收集器为您关闭文件,因为这种行为既不保证也不方便实现。另外,Python不能保证在调用之前完成对文件的写入。关闭()。
运行这段代码,至少在我的例子中,不会打印出journal1.txt内容:
所有丢失的东西都会在这里找到吗?
只有心灵纯洁的人才能拥有神奇的头发
不是自然发生的?
会导致轻微的重力异常!
上下文管理器在实践中,请始终记住调用close()可能是一件非常痛苦的事情,尤其是当您考虑到打开文件时可能出现的错误时。幸运的是,有一个更简洁的方法:上下文管理器!
上下文管理器由Python中的with语句定义。我可以使用以下语法重写我以前的代码:
用open(journal1.txt , r )作为文件:
对于文件中的行:
Print(line)调用open()函数。如果成功,生成的TextIOWrapper对象将存储在中的文件中,并可在with语句的正文中使用。一旦控制权离开with语句,file.close()将被隐式调用;你永远也不需要记得打电话给它!
我们将在下一章更深入地介绍这一点。
模式本文提到了几种可用于open()的模式:
r打开文件进行读取(默认)。打开或创建一个文件来写,删除(截断)其内容。a打开或创建要写入的文件,但追加到末尾而不是截断。x创建并打开一个新文件进行写入;它无法打开现有文件。打开文件进行读写(见下表)。t以文本模式处理文件(默认)。以二进制模式处理文件。这些模式标志可以组合使用。例如,在二进制模式下,a b允许写和读,其中写被附加到文件的末尾。
一个标志总是与另一个标志结合在一起。与R结合时,增加了A的功能,但从文件开头开始(不截断)。当与W、A或x组合时,它还允许读取。
使用此表可以最好地理解不同标志的行为:
r r w w a a
- -
允许读取
允许写入
创建新文件
打开现有文件
擦除文件内容
允许搜索
起始位置
位置在末尾
读我们可以使用read(),readline()或者读取行()函数以文本模式读取文件,也可以直接迭代
当然,这需要使用适当的文件模式标志打开文件进行读取(请参阅"文件模式"部分)。如果需要检查对象文件是否可以读取,请使用file.readable()函数。
让我们对比一下读取文件的三种方式:
读取()读取()函数将文件的全部内容作为一个长字符串读取。
用打开( journal1.txt , r )作为文件:
contents=file.read()
打印(目录)
#这是所有丢失的东西被找到的地方吗?
#魔发只为心灵纯洁的人准备
#不是自然发生的?
#可能会导致轻微的重力异常!或者,你可以告诉阅读()从文件流中读取的最大字符数:
用打开( journal1.txt , r )作为文件:
contents=file.read(20)
打印(目录)
#这是哪里
读取线()函数的行为与阅读()完全相同,只是它在遇到换行符时停止读取。换行符包含在返回的字符串中。
用打开( journal1.txt , r )作为文件:
contents=file.readline()
打印(目录)
#这是所有丢失的东西被找到的地方吗?与阅读()一样,你可以指定要读取的最大字符数:
用打开( journal1.txt , r )作为文件:
contents=file.readline(20)
打印(目录)
#这是哪里
读取行()读取行()函数以字符串列表的形式返回整个文件,每个字符串为一行。
用打开( journal1.txt , r )作为文件:
contents=file.readlines()
对于内容中的丙:
打印(三)
#这是所有丢失的东西被找到的地方吗?
#
#魔发只为心灵纯洁的人准备
#
#不是自然发生的?
#
#可能会导致轻微的重力异常!
#你会注意到每一行都包含换行符。我们可以通过在每个字符串上调用.条状()函数来删除它。
用打开( journal1.txt , r )作为文件:
contents=file.readlines()
对于内容中的丙:
print(c.strip())
#这是所有丢失的东西被找到的地方吗?
#魔发只为心灵纯洁的人准备
#不是自然发生的?
#可能会导致轻微的重力异常!你还可以通过指定最大字符数来限制从文件中读取的内容。然而,与以前不同的是,这不是硬性限制。相反,一旦到目前为止从所有行读取的字符总数超过了指定的限制,则只会读取当前行的其余部分。
通过比较阅读()和读取行()可以最好地理解这一点。首先,我将阅读限制为60个字符:
用打开( journal1.txt , r )作为文件:
contents=file.read(60)
打印(目录)
#这是所有丢失的东西被找到的地方吗?
#神奇的头发将读取行()与使用60个字符的"提示"进行比较:
用打开( journal1.txt , r )作为文件:
contents=file.readlines(60)
对于内容中的丙:
print(c.strip())
#这是所有丢失的东西被找到的地方吗?
#魔发只为心灵纯洁的人准备在第二个示例中,读取前两行的全部内容,但不再读取。
与其他两个函数不同,读取行()总是读取整行。
迭代如你之前所见,我们可以直接迭代文件:
用打开( journal1.txt , r )作为文件:
对于文件中的行:
打印(行)
#这是所有丢失的东西被找到的地方吗?
#魔发只为心灵纯洁的人准备
#不是自然发生的?
#可能会导致轻微的重力异常!这在功能上与以下内容相同:
用打开( journal1.txt , r )作为文件:
对于file.readlines()中的行:
print (line)和print(line)的区别在于第一种方法直接迭代比较懒,而第二种方法在迭代内容之前先读取整个文件。
使用write()或writelines()函数,我们可以用几乎相同的方式编写文件。
这要求打开文件进行写入(参见“文件模式”一节)。file.writable()函数可用于检查file对象是否可写。
在本节的示例中,我将在底部的注释中显示文件内容。
函数的作用是:将一个给定的行写到一个文件中。
我可以使用write()将整个多行字符串写入一个名为journal3.txt的新文件,如下所示:
如果你有足够的公路旅行
很有可能,你已经看到了
某些保险杠贴纸:
神秘小屋是什么?
用open(journal3.txt , x )作为文件:
file.write(条目)
#如果你有足够的公路旅行
#机会是,你已经看到了
#某些保险杠贴纸:
#神秘小屋是什么?
#只要journal3.txt不存在,就会用给定的内容创建。
我可以用W文件模式覆盖journal3.txt的全部内容:
用open(journal3.txt , w )作为文件:
file.write(侏儒\ n虚弱?\n )
#侏儒
#弱点?
#注意:注意你的文件模式!w删除文件的所有内容。使用或写入文件的末尾。
我可以使用A文件模式附加到文件:
用open(journal3.txt , a )作为文件:
file.write(吹叶机\n )
#侏儒
#弱点?
#吹叶机
# write()函数返回一个整数,表示写入的字符数。
函数的作用是:将字符串列表写入文件。
线条=[
终于平安回来了\n ,
从最奇怪的一天开始,
在重力瀑布。\n
]
用open(journal3.txt , w )作为文件:
file.writelines(行)
#终于平安归来
#来自最奇怪的一天
#在重力瀑布。
#与write()不同,writelines()函数只返回None。
search file.seek()函数允许您在文件对象文件中逐个字符地来回移动。在处理文本流时,它接受一个参数:一个正整数,表示要移动到的新位置,以及从开始的字符数。
除了改变位置之外,这个file.seek()函数将返回一个表示文件中新的绝对位置的整数。您可以使用file.tell()来获取文件的当前位置。
r文件模式最好与seek()函数一起使用,尽管它可以与除A和A之外的任何其他文件模式一起使用。
我将首先使用seek()函数读取journal1.txt文件的一部分:
用open(journal1.txt , r )作为文件:
file.seek(50)
contents=file.read(5)
打印(目录)
# MAGIC我将编写一个新的初始版本的journal3.txt文件:
用open(journal3.txt , w )作为文件:
file.write(浮动眼球)
#浮动眼球我可以用这个R模式来改变这个文件的一部分。
注意:write()命令将总是覆盖文件的现有内容,除非您追加到文件的末尾。为了无损地将文本插入文件,通常最好将整个内容作为字符串(或列表)读取,编辑字符串,然后写回。
在这里,我会用“无谓!”替换“眼球”一词:
用open(journal3.txt , r )作为文件:
file.seek(9)
file.write(胡说!)
#漂浮的废话!打开文件后,我从开头移到第9个字符,然后write()就是新的数据。
使用二进制搜索当您以二进制模式(B)打开文件时,您可以使用两个参数而不是一个参数以更动态的方式在文件中移动:
Offset:字符移动的距离(可以是负数)当:计算偏移量的位置:0表示文件的起始位置(默认),1表示当前位置,2表示文件的结束位置。不幸的是,使用whence参数不适用于以文本模式打开的文件。
错误与处理文件相关的四种最常见的错误如下:
文件发现错误r和r模式要求文件在打开前存在。否则,将引发FileNotFoundError:
尝试:
用open(notreal.txt , r )作为文件:
print(file.read())
除了FileNotFoundError作为e:
打印(e)
FileExistsError x和x文件模式专门用于创建新文件。如果文件已经存在,将引发FileExistsError错误:
尝试:
用open(journal3.txt , x )作为文件:
print(file.read())
除了FileExistsError作为e:
打印(e)
UnsupportedOperation:每当您试图读取一个只为写而打开的文件或写一个只为读而打开的文件时,都会出现错误io。将引发不支持操作:
导入io
尝试:
用open(journal3.txt , w )作为文件:
print(file.read())
除了木卫一。不支持e类操作:
打印(e)
尝试:
用open(journal3.txt , r )作为文件:
file.write( )
除了木卫一。不支持e类操作:
打印换行符的问题。有些聪明的读者会记得,虽然UNIX使用\n作为行分隔符,但Windows使用\ r \r\n,当我们读写文档时,它一定很重要吧?
事实上,Python在幕后为我们抽象了这一点。在文本模式下写文件时总是用作行分隔符,与操作系统无关!\n
到目前为止,我只使用了与代码在同一个文件夹中的文件,但这很少是我们想要的!我们需要能够建立文件路径。
问题是文件路径在所有系统上都是不同的。UNIX风格的系统,如macOS和Linux,使用UNIX文件路径约定,而Windows使用完全不同的方案。我们的解决方案必须对两者都有效,这意味着艰难的道路不是一个选项。
为了解决这个问题,Python提供了两个模块:os和pathlib。
创建路径Python实际上提供了多个用于构建路径的类,这取决于您的特定需求。然而,在大多数情况下,您应该只使用pathlib。小路
假设我想创建一个名为。dead_simple_python放在当前用户的主文件夹中,然后将文件写入该位置。我会这样做:
首先,我创建一个Path()对象,它指向我最终需要的目录(而不是文件)。
在Path()构造函数中,我将路径的每个部分作为单独的字符串传递。我可以使用类方法Path.home()来获取用户目录的路径。
从pathlib导入路径
导入操作系统
File _ path=path (path.home(),。dead _ simple _ python’)。接下来,我将使用file_path.exists()来检查路径是否已经存在。如果它不存在,我将使用os.makedirs函数创建路径中缺少的任何目录:
如果不是file_path.exists():
Os.makedirs(file_path)最后,我可以将文件名添加到已经拥有的path对象中,然后打开文件进行写入:
file _ path=file _ path . join path( journal 4 . txt )
使用file_path.open(w )作为文件:
线条=[
如果你曾经自驾游过,
穿过西北太平洋,你已经\n ,
可能见过一个汽车保险杠贴纸,
一个叫重力瀑布的地方。\n
]
你会注意到我用了file_path.open(w )而不是open(file_path, w )。从技术上来说,两个函数是完全一样的,虽然成员函数是首选。
相对路径open(journal1.txt )是有效的,因为它是从执行代码的目录开始的相对路径。
如果我的代码所在的目录中有一个日志/目录,我可以使用它:
从pathlib导入路径
file_path=Path(journals , journal1.txt )
使用file_path.open(r )作为文件:
Print(file.read())只要我不是以绝对路径开始,比如Path.home()生成的路径,路径都是相对的。
但是如果我想向上而不是向下移动一个目录呢?你可以试着用.但是正如你可能猜到的,它不能保证在所有操作系统上都是可移植的。相反,我可以使用os.pardir移动到上一个目录。
假设我们有如下的目录结构:
例子
电码
read_file.py
期刊
journal1.txt如果我在path_relative2/code中运行python read_file.py,可以通过以下方式访问journal1.txt:
从pathlib导入路径
导入操作系统
file_path=Path(os.pardir, journals , journal1.txt )
使用file_path.open(r )作为文件:
print(file.read())
总结只是简单介绍了如何处理文件,但希望这已经解开了open()函数和Path对象的谜团。这里有一个快速回顾:
open()函数有几种模式:R用于读取,W用于截断和写入,X用于创建和写入,A用于追加。增加其中的任何一项都会增加缺失的功能,无论是读还是写。你必须记得关闭所有打开的文件。您可以使用open()手动完成这项工作,或者.如果用语句打开文件(上下文管理器),文件将自动关闭。Myfile.seek()允许您更改打开的文件Myfile中的位置。这不适用于模式R、A或A。Path对象允许您创建一个可移动的路径,它是由传递给path()初始化器的字符串构建的。可以直接在Path对象上调用open()。使用Path.home()获取当前用户个人文件夹的绝对路径。使用os.pardir访问父目录(相当于.在Unix上)。)在下一节中,我将更深入地探讨上下文管理器。
原创作品来自程,
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。