首页 > 学院 > 开发设计 > 正文

文件

2019-11-06 06:38:51
字体:
来源:转载
供稿:网友

打开,open()

在Python里打开一个文件很简单:

a_file = open('examples/chinese.txt', encoding='utf-8')

Python有一个内置函数 open(),但需要注意:

Windows使用反斜杠来表示子目录,但是Mac OS X和linux使用斜杠。但是,在Python中,斜杠永远都是正确的,即使是在Windows环境下。filename,”参数是一个字符串。所有现代的操作系统(甚至Windows!)使用Unicode编码方式来存储文件名和目录名。Python 3全面支持非ASCII编码的路径。文件不一定需要在本地磁盘上。也许你挂载了一个网络驱动器。它也可以是一个完全虚拟的文件系统(an entirely virtual filesystem)上的文件。只要你的操作系统认为它是一个文件,并且能够以文件的方式访问,那么,Python就能打开它。 下面>>> a_file = open('examples/chinese.txt', encoding='utf-8')>>> a_file.mode ③'r'

如果在打开文件的时候没有指定访问模式,Python默认设置模式为’r’,意思是“在文本模式下以只读的方式打开。”在这章的后面你会看到,文件的访问模式有各种用途;不同模式能够使你写入一个文件,追加到一个文件,或者以二进制模式打开一个文件(在这种情况下,你处理的是字节,不再是字符)。

读取

>>> a_file = open('examples/chinese.txt', encoding='utf-8')>>> a_file.read() ①'Dive Into Python 是为有经验的程序员编写的一本 Python 书。/n'>>> a_file.read() ②''只要成功打开了一个文件(并且指定了正确的编码方式),你只需要调用流对象的read()方法即可以读取它。返回的结果是文件的一个字符串表示。也许你会感到意外,再次读取文件不会产生一个异常。Python不认为到达了文件末尾(end-of-file)还继续执行读取操作是一个错误;这种情况下,它只是简单地返回一个空字符串。

其他

seek()方法使定位到文件中的特定字节。 read()方法可以使用一个可选的参数,即所要读取的字符个数。 seek()和tell()方法总是以字节的方式计数,但是,由于你是以文本文件的方式打开的,read()方法以字符的个数计数。

>>> a_file.read() ①''>>> a_file.seek(0) ②0>>> a_file.read(16) ③'Dive Into Python'>>> a_file.read(1) ④' '>>> a_file.read(1)'是'>>> a_file.tell() ⑤20>>> a_file.seek(17) ①17>>> a_file.read(1) ②'是'>>> a_file.tell() ③20>>> a_file.seek(18) ①18>>> a_file.read(1) ②Traceback (most recent call last): File "<pyshell#12>", line 1, in <module> a_file.read(1) File "C:/Python31/lib/codecs.py", line 300, in decode (result, consumed) = self._buffer_decode(data, self.errors, final)UnicodeDecodeError: 'utf8' codec can't decode byte 0x98 in position 0: unexpected code byte#定位到第18th个字节,然后试图读取一个字符。但失败了,因为在第18个字节处不存在字符。

关闭文件,close

当已经完成了对文件的操作后就立即关闭它们,这很重要。

>>> a_file.close()

然而,这还不够(anticlimactic)。流对象a_file仍然存在;调用close()方法并没有把对象本身销毁。所以这并不是非常有效。

>>> a_file.close() >>> a_file.closed True

已经关闭了的流对象确实还有一个有用的属性:closed用来确认文件是否已经被关闭了。

改进

try..finally也行。但是with更好

流对象有一个显式的close()方法,但是如果代码有缺陷,在调用close()方法以前就崩溃了呢 。所以使用with()。

with open('examples/chinese.txt', encoding='utf-8') as a_file: a_file.seek(17) a_character = a_file.read(1) PRint(a_character)

这段代码调用了open()函数,但是它却一直没有调用a_file.close()。with语句引出一个代码块,就像if语句或者for循环一样。在这个代码块里,你可以使用变量a_file作为open()函数返回的流对象的引用。所以流对象的常规方法都是可用的 — seek(),read(),无论你想要调用什么。当with块结束时,Python自动调用a_file.close()。

关于with

从技术上说,with语句创建了一个运行时环境(runtime context)。 with语句不只是针对文件而言的;它是一个用来创建运行时环境的通用框架(generic framework),告诉对象它们正在进入和离开一个运行时环境。 如果该对象是流对象,那么它就会做一些类似文件对象一样有用的动作(就像自动关闭文件!)。但是那个行为是被流对象自身定义的,而不是在with语句中。还有许多跟文件无关的使用上下文管理器(context manager)的方法。在这章的后面可以看到,你甚至可以自己创建它们。

实例:一次读取一行数据

line_number = 0with open('examples/favorite-people.txt', encoding='utf-8') as a_file: ① for a_line in a_file: ② line_number += 1 print('{:>4} {}'.format(line_number, a_line.rstrip())) ③使用with语句,安全地打开这个文件,然后让Python为你关闭它。 2.为了一次读取文件的一行,使用for循环。是的,除了像read()这样显式的方法,流对象也是一个迭代器(iterator),它能在你每次请求一个值时分离出单独的一行。使用字符串的format()方法,你可以打印出行号和行自身。格式说明符{:>4}的意思是“使用最多四个空格使之右对齐,然后打印此参数。”变量a_line是包括回车符等在内的完整的一行。字符串方法rstrip()可以去掉尾随的空白符,包括回车符。 如果结果是这样,也许你正在使用Python 3.0。你真的应该升级到Python 3.1。print('{0:>4} {1}'.format(line_number, a_line.rstrip()))

Python 3.0支持字符串格式化,但是只支持显式编号了的格式说明符。Python 3.1允许你在格式说明符里省略参数索引号。作为比照,下面是一个Python 3.0兼容的版本。

写入

两种方式:

1.“写”模式会重写文件。传递mode=’w’参数给open()函数。 2.“追加”模式会在文件末尾添加数据。传递mode=’a’参数给open()函数。

如果文件不存在,两种模式下都会自动创建新文件。最后,在完成写入后你应该马上关闭文件,释放文件句柄(file handle),并且保证数据被完整地写入到了磁盘。 结合with会让编程更简单。

>>> with open('test.log', mode='w', encoding='utf-8') as a_file: ①... a_file.write('test succeeded') ②>>> with open('test.log', encoding='utf-8') as a_file:... print(a_file.read()) test succeeded>>> with open('test.log', mode='a', encoding='utf-8') as a_file: ③... a_file.write('and again')>>> with open('test.log', encoding='utf-8') as a_file:... print(a_file.read()) test succeededand again ④

你是否注意到当你在打开文件用于写入数据的时候传递给open()函数的encoding参数。它“非常重要”,不要忽略了!实际上你不能直接把字符写入到文件;字符只是一种抽象。为了写入字符到文件,Python需要知道如何将字符串转换为字节序列。唯一能保证正确地执行转换的方法就是当你为写入而打开一个文件的时候,指定encoding参数。

二进制文件

>>> an_image = open('examples/beauregard.jpg', mode='rb') ①>>> an_image.mode ② 'rb'

用二进制模式打开文件很简单,但是很精细。与文本模式唯一不同的是mode参数包含一个字符’b’。 字符 不等于 字节!!!

高级玩法:非文件来源的流对象

使用read()方法即可从虚拟文件读取数据。 这听起来跟你从打开一个真实文件得到的流对象一样。不同之处在于你不再受限于真实的文件。能够“读取”的输入源可以是任何东西:网页,内存中的字符串,甚至是另外一个程序的输出。只要你的函数使用的是流对象,调用对象的read()方法,你可以处理任何行为与文件类似的输入源,而不需要为每种类型的输入指定特别的代码。

>>> a_string = 'PapayaWhip is the new black.'>>> import io ①>>> a_file = io.StringIO(a_string) ②>>> a_file.read() ③'PapayaWhip is the new black.'io模块定义了StringIO类,你可以使用它来把内存中的字符串当作文件来处理。为了从字符串创建一个流对象,可以把想要作为“文件”使用的字符串传递给io.StringIO()来创建一个StringIO的实例。调用read()方法“读取”整个“文件”,以StringIO对象为例即返回原字符串。 io.StringIO让你能够将一个字符串作为文本文件来看待。另外还有一个io.ByteIO类,它允许你将字节数组当做二进制文件来处理。

处理压缩文件

gzip和bzip2是非Windows操作系统下最流行的两种压缩方式。

gzip模块允许你创建用来读写gzip压缩文件的流对象。该流对象支持read()方法(如果你以读取模式打开)或者write()方法(如果你以写入模式打开)。这就意味着,你可以使用从普通文件那儿学到的技术来直接读写gzip压缩文件。 它也支持with语句,所以当你完成了对gzip压缩文件的操作,Python可以为你自动关闭它。

Linux命令

you@localhost:~$ gunzip out.log.gz ③ you@localhost:~$ cat out.log ④ A nine mile walk is no joke, especially in the rain.gunzip命令(发音:“gee-unzip”)解压缩文件然后保存其内容到一个与原来压缩文件同名的新文件中,并去掉其.gz扩展名。cat命令显示文件的内容。当前文件包含了原来你从Python shell直接写入到压缩文件out.log.gz的那个字符串。

标准输入、输出和错误(关于模块sys)

sys.stdin, sys.stdout, sys.stderr,它们分别是标准输入,标准输出和标准错误。

>>> import sys>>> for i in range(3):... sys.stdout.write('is the') ②is theis theis the>>> for i in range(3):... sys.stderr.write('new black') ③new blacknew blacknew black>>> sys.stdout.read()Traceback (most recent call last): File "<stdin>", line 1, in <module>IOError: not readable

sys.stdout和sys.stderr都是流对象,但是他们都只支持写入。试图调用他们的read()方法会引发IOError异常。


上一篇:golang获取命令行参数

下一篇:matlab时间

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表