Python学习:文件

要使用文本文件中的信息,首先需要将信息读取到内存中。为此,你可以一次性读取文件的
全部内容,也可以以每次一行的方式逐步读取。

文件操作的基本方法

#掌握
f.read() #读取所有内容,光标移动到文件末尾
f.readline() #读取一行内容,光标移动到第二行首部
f.readlines() #读取每一行内容,存放于列表中

f.write('1111\n222\n') #针对文本模式的写,需要自己写换行符
f.write('1111\n222\n'.encode('utf-8')) #针对b模式的写,需要自己写换行符
f.writelines(['333\n','444\n']) #文件模式
f.writelines([bytes('333\n',encoding='utf-8'),'444\n'.encode('utf-8')]) #b模式

#了解
f.readable() #文件是否可读
f.writable() #文件是否可读
f.closed #文件是否关闭
f.encoding #如果文件打开模式为b,则没有该属性
f.flush() #立刻将文件内容从内存刷到硬盘
f.name

读取整个文件

       Python 允许你将内容写入文件, 方式与 print()函数将字符串“写” 到屏幕上类似。但是, 如果打开文件时用读模式, 就不能写入文件。你需要以“写入纯文本模式”或“添加纯文本模式” 打开该文件, 或简称为“写模式” 和“添加模式”。写模式将覆写原有的文件,从头开始,就像你用一个新值覆写一个变量的值。
       将’w’作为第二个参数传递给 open(),以写模式打开该文件。不同的是,添加模式将在已有文件的末尾添加文本。你可以认为这类似向一个变量中的列表添加内容,而不是完全覆写该变量。'a’作为第二个参数传递给 open(),以添加模式打开该文件。如果传递给 open()的文件名不存在,写模式和添加模式都会创建一个新的空文件。在读取或写入文件后, 调用 close()方法, 然后才能再次打开该文件。

文本文件
下面的程序打开并读取这个文件,再将其内容显示到屏幕上:

#file_reader.py
with open('pi_digits.txt') as file_object:
	contents = file_object.read()
	print(contents)

要以任何方式使用文件——哪怕仅仅是打印其内容,都得先打开文件,这样才能访问它。
函数open()接受一个参数:要打开的文件的名称。
Python在当前执行的文件所在的目录中查找指定的文件。在这个示例中,当前运行的是file_reader.py,因此Python在file_reader.py所在的目录中查找pi_digits.txt。函数open()返回一个表示文件的对象。在这里, open(‘pi_digits.txt’)返回一个表示文件pi_digits.txt的对象; Python将这个对象存储在我们将在后面使用的变量中。
关键字with在不再需要访问文件后将其关闭。在这个程序中,注意到我们调用了open(),但没有调用close();你也可以调用open()和close()来打开和关闭文件,但这样做时,如果程序存在bug,导致close()语句未执行,文件将不会关闭。
有了表示pi_digits.txt的文件对象后,我们使用方法read()读取这个文件的全部内容,并将其作为一个长长的字符串存储在变量contents中。
相比于原始文件,该输出唯一不同的地方是末尾多了一个空行。为何会多出这个空行呢?因
为read()到达文件末尾时返回一个空字符串,而将这个空字符串显示出来时就是一个空行。要删
除多出来的空行,可在print语句中使用rstrip():

with open('pi_digits.txt') as file_object:
	contents = file_object.read()
	print(contents.rstrip())

逐行读取

读取文件时,常常需要检查其中的每一行:你可能要在文件中查找特定的信息,或者要以某种方式修改文件中的文本。

例如,你可能要遍历一个包含天气数据的文件,并使用天气描述中包含字样sunny的行。在新闻报道中,你可能会查找包含标签的行,并按特定的格式设置它。

要以每次一行的方式检查文件,可对文件对象使用for循环:

filename = 'pi_digits.txt'
with open(filename) as file_object:
	for line in file_object:
		print(line)

将要读取的文件的名称存储在变量filename中,这是使用文件时一种常见的做法。
调用open()后,将一个表示文件及其内容的对象存储到了变量file_object中。这里也使用了关键字with,让Python负责妥善地打开和关闭文件。
输出:
在这里插入图片描述
我们打印每一行时,发现空白行更多了:因为在这个文件中,每行的末尾都有一个看不见的换行符,而print语句也会加上一个换行符,因此每行末尾都有两个换行符:一个来自文件,另一个来自print
语句。要消除这些多余的空白行,可在print语句中使用rstrip():

filename = 'pi_digits.txt'
with open(filename) as file_object:
	for line in file_object:
		print(line.rstrip())

创建一个包含文件各行内容的列表

使用关键字with时, open()返回的文件对象只在with代码块内可用。如果要在with代码块外访问文件的内容,可在with代码块内将文件的各行存储在一个列表中,并在with代码块外使用该列表:你可以立即处理文件的各个部分,也可推迟到程序后面再处理。
下面的示例在with代码块中将文件pi_digits.txt的各行存储在一个列表中,再在with代码块外
打印它们:

filename = 'pi_digits.txt'
with open(filename) as file_object:
	lines = file_object.readlines()

for line in lines:
	print(line.rstrip())

方法readlines()从文件中读取每一行,并将其存储在一个列表中;接下来,该列表被存储到变量lines中;

使用文件的内容

将文件读取到内存中后,就可以以任何方式使用这些数据了。

filename = 'pi_digits.txt'
with open(filename) as file_object:
	lines = file_object.readlines()

pi_string = ''

for line in lines:
	pi_string += line.strip()

print(pi_string)
print(len(pi_string))

注 意 \color{HotPink}{注意} 读取文本文件时, Python将其中的所有文本都解读为字符串。如果你读取的是数字,并要将其作为数值使用,就必须使用函数int()将其转换为整数,或使用函数float()将其转换为浮点数。

包含一百万位的大型文件

如果我们有一个文本文件,其中包含精确到小数点后1 000 000位而不是30位的圆周率值,也可创建一个包含所有这些数字的字符串。为此,我们无需对前面的程序做任何修改,只需将这个文件传递给它即可。

filename = 'pi_million_digits.txt'

with open(filename) as file_object:
	lines = file_object.readlines()

pi_string = ''

for line in lines:
	pi_string += line.strip()

print(pi_string[:52] + "...")
print(len(pi_string))

对于你可处理的数据量, Python没有任何限制;只要系统的内存足够多,你想处理多少数据都可以。

圆周率值中包含你的生日吗

想知道自己的生日是否包含在圆周率值中。下面来扩展刚才编写的程序,以确定某个人的生日是否包含在圆周率值的前1 000 000位中。为此,可将生日表示为一个由数字组成的字符串,再检查这个字符串是否包含在pi_string中:

filename = 'pi_million_digits.txt'
with open(filename) as file_object:
	lines = file_object.readlines()
pi_string = ''
for line in lines:
	pi_string += line.rstrip()

birthday = input("Enter your birthday, in the form mmddyy: ")
if birthday in pi_string:
	print("Your birthday appears in the first million digits of pi!")
else:
	print("Your birthday does not appear in the first million digits of pi.")

写入文件

保存数据的最简单的方式之一是将其写入到文件中。通过将输出写入文件,即便关闭包含程序输出的终端窗口,这些输出也依然存在:你可以在程序结束运行后查看这些输出,可与别人分享输出文件,还可编写程序来将这些输出读取到内存中并进行处理。

写入空文件

要将文本写入文件,你在调用open()时需要提供另一个实参,告诉Python你要写入打开的文件。为明白其中的工作原理,我们来将一条简单的消息存储到文件中,而不是将其打印到屏幕上:

filename = 'programming.txt'
with open(filename, 'w') as file_object:
	file_object.write("I love programming.")

调用open()时提供了两个实参。第一个实参也是要打开的文件的名称;第二个实参( ‘w’)告诉Python,我们要以写入模式打开这个文件。打开文件时,可指定读取模式( ‘r’)、 写入模式( ‘w’)、 附加模式( ‘a’)或让你能够读取和写入文件的模式( ‘r+’)。如果你省略了模式实参,Python将以默认的只读模式打开文件。
如果你要写入的文件不存在,函数open()将自动创建它。然而,以写入( ‘w’)模式打开文件时千万要小心,因为如果指定的文件已经存在, Python将在返回文件对象前清空该文件。
使用文件对象的方法write()将一个字符串写入文件。这个程序没有终端输出,但如果你打开文件programming.txt,
注 意 P y t h o n 只 能 将 字 符 串 写 入 文 本 文 件 。 要 将 数 值 数 据 存 储 到 文 本 文 件 中 , 必 须 先 使 用 函 数 s t r ( ) 将 其 转 换 为 字 符 串 格 式 \color{HotPink}{注意 Python只能将字符串写入文本文件。要将数值数据存储到文本文件中,必须先使用函数str()将其转换为字符串格式} Python使str()

写入多行

函数write()不会在你写入的文本末尾添加换行符,因此如果你写入多行时没有指定换行符,文件看起来可能不是你希望的那样:

filename = 'programming.txt'
with open(filename, 'w') as file_object:
	file_object.write("I love programming.")
	file_object.write("I love creating new games.")
结果:I love programming.I love creating new games.

要让每个字符串都单独占一行,需要在write()语句中包含换行符:

filename = 'programming.txt'
with open(filename, 'w') as file_object:
	file_object.write("I love programming.\n")
	file_object.write("I love creating new games.\n")

附加到文件

如果你要给文件添加内容,而不是覆盖原有的内容,可以附加模式打开文件。你以附加模式打开文件时, Python不会在返回文件对象前清空文件,而你写入到文件的行都将添加到文件末尾。如果指定的文件不存在, Python将为你创建一个空文件。

filename = 'programming.txt'
with open(filename, 'a') as file_object:
	file_object.write("I also love finding meaning in large datasets.\n")
	file_object.write("I love creating apps that can run in a browser.\n")

用 shelve 模块保存变量

利用 shelve 模块, 你可以将 Python 程序中的变量保存到二进制的 shelf 文件中。这样, 程序就可以从硬盘中恢复变量的数据。 shelve 模块让你在程序中添加“保存”和“打开” 功能。例如, 如果运行一个程序,并输入了一些配置设置,就可以将这些设置保存到一个 shelf 文件,然后让程序下一次运行时加载它们。

shelfFile = shelve.open('mydata')
cats = ['Zophie', 'Pooka', 'Simon']
shelfFile['cats'] = cats
print(shelfFile['cats'])
输出:['Zophie', 'Pooka', 'Simon']

输入 shelfFile[‘cats’]将返回我们前面保存的同一个列表,所以我们就知道该列表得到了正确存储,
要利用shelve 模块读写数据,首先要导入它。调用函数shelve.open()并传入一个文件名,然后将返回的值保存在一个变量中。可以对这个变量的 shelf 值进行修改,就像它是一个字典一样。当你完成时,在这个值上调用close()。这里,我们的shelf 值保存在shelfFile中。我们创建了一个列表cats,并写下shelfFile[‘cats’] =cats,将该列表保存在shelfFile 中,作为键’cats’关联的值(就像在字典中一样)。然后我们在shelfFile 上调用close()。
        就像字典一样, shelf 值有 keys()和 values()方法, 返回 shelf 中键和值的类似列表的值。因为这些方法返回类似列表的值, 而不是真正的列表, 所以应该将它们传递给 list()函数, 取得列表的形式。

shelfFile = shelve.open('mydata')
cats = ['Zophie', 'Pooka', 'Simon']
shelfFile['cats'] = cats
print(shelfFile['cats'])
List=list(shelfFile.keys())
print(List)
输出:
['Zophie', 'Pooka', 'Simon']
['cats']

用 pprint.pformat()函数保存变量

pprint.pprint()函数列表或字典中的内容“漂亮打印” 到屏幕, 而 pprint.pformat()函数将返回同样的文本字符串,但不是打印它。这个字符串不仅是易于阅读的格式, 同时也是语法上正确的 Python 代码。 假定你有一个字典, 保存在一个变量中, 你希望保存这个变量和它的内容, 以便将来使用。
pprint.pformat()函数将提供一个字符串, 你可以将它写入.py文件。该文件将成为你自己的模块, 如果你需要使用存储在其中的变量, 就可以导入它。

异常

Python使用被称为异常的特殊对象来管理程序执行期间发生的错误。每当发生让Python不知所措的错误时,它都会创建一个异常对象。如果你编写了处理该异常的代码,程序将继续运行;如果你未对异常进行处理,程序将停止,并显示一个traceback,其中包含有关异常的报告。异常是使用try-xcept代码块处理的。 try-except代码块让Python执行指定的操作,同时告诉Python发生异常时怎么办。使用了try-except代码块时,即便出现异常,程序也将继续运行:显示你编写的友好的错误消息,而不是令用户迷惑的traceback。

>>> import pprint
>>> cats = [{'name': 'Zophie', 'desc': 'chubby'}, {'name': 'Pooka', 'desc': 'fluffy'}]
>>> pprint.pformat(cats)
"[{'desc': 'chubby', 'name': 'Zophie'}, {'desc': 'fluffy', 'name': 'Pooka'}]"
>>> fileObj = open('myCats.py', 'w')
>>> fileObj.write('cats = ' + pprint.pformat(cats) + '\n')
83
>>> fileObj.close()

导入了 pprint,以便能使用 pprint.pformat()。我们有一个字典的列表,保存在变量 cats 中。为了让 cats 中的列表在关闭交互式环境后仍然可用,我们利用pprint.pformat(),将它返回为一个字符串。当我们有了 cats 中数据的字符串形式,就很容易将该字符串写入一个文件,我们将它命名为 myCats.py

生成随机的测验试卷文件

import random

# The quiz data. Keys are states and values are their capitals.
capitals = {'Alabama': 'Montgomery', 'Alaska': 'Juneau', 'Arizona': 'Phoenix',
    'Arkansas': 'Little Rock', 'California': 'Sacramento', 'Colorado': 'Denver',
    'Connecticut': 'Hartford', 'Delaware': 'Dover', 'Florida': 'Tallahassee',
    'Georgia': 'Atlanta', 'Hawaii': 'Honolulu', 'Idaho': 'Boise', 'Illinois':
    'Springfield', 'Indiana': 'Indianapolis', 'Iowa': 'Des Moines', 'Kansas':
    'Topeka', 'Kentucky': 'Frankfort', 'Louisiana': 'Baton Rouge', 'Maine':
    'Augusta', 'Maryland': 'Annapolis', 'Massachusetts': 'Boston', 'Michigan':
    'Lansing', 'Minnesota': 'Saint Paul', 'Mississippi': 'Jackson', 'Missouri':
    'Jefferson City', 'Montana': 'Helena', 'Nebraska': 'Lincoln', 'Nevada':
    'Carson City', 'New Hampshire': 'Concord', 'New Jersey': 'Trenton',
    'NewMexico': 'Santa Fe', 'New York': 'Albany', 'North Carolina': 'Raleigh',
    'North Dakota': 'Bismarck', 'Ohio': 'Columbus', 'Oklahoma': 'Oklahoma City',
    'Oregon': 'Salem', 'Pennsylvania': 'Harrisburg', 'Rhode Island': 'Providence',
    'South Carolina': 'Columbia', 'South Dakota': 'Pierre', 'Tennessee':
    'Nashville', 'Texas': 'Austin', 'Utah': 'Salt Lake City', 'Vermont':
    'Montpelier', 'Virginia': 'Richmond', 'Washington': 'Olympia',
    'WestVirginia': 'Charleston', 'Wisconsin': 'Madison', 'Wyoming': 'Cheyenne'}

# Generate 35 quiz files.
for quizNum in range(35):

    # Create the quiz and answer key files.
    quizFile = open('capitalsquiz%s.txt' % (quizNum + 1), 'w')
    answerKeyFile = open('capitalsquiz_answers%s.txt' % (quizNum + 1), 'w')

    # Write out the header for the quiz.
    quizFile.write('Name:\n\nDate:\n\nPeriod:\n\n')
    quizFile.write((' ' * 20) + 'State Capitals Quiz (Form %s)' % (quizNum + 1))
    quizFile.write('\n\n')

    # Shuffle the order of the states.
    states = list(capitals.keys())
    random.shuffle(states)

    # Loop through all 50 states, making a question for each.
    for questionNum in range(50):

        # Get right and wrong answers.
        correctAnswer = capitals[states[questionNum]]
        wrongAnswers = list(capitals.values())
        del wrongAnswers[wrongAnswers.index(correctAnswer)]
        wrongAnswers = random.sample(wrongAnswers, 3)
        answerOptions = wrongAnswers + [correctAnswer]
        random.shuffle(answerOptions)

        # Write the question and the answer options to the quiz file.
        quizFile.write('%s. What is the capital of %s?\n' % (questionNum + 1,states[questionNum]))

        for i in range(4):
            quizFile.write(' %s. %s\n' % ('ABCD'[i], answerOptions[i]))
        quizFile.write('\n')

        # Write the answer key to a file.
        answerKeyFile.write('%s. %s\n' % (questionNum + 1, 'ABCD'[
            answerOptions.index(correctAnswer)]))

   quizFile.close()
   answerKeyFile.close()

分析文本

下面来提取童话Alice in Wonderland的文本,并尝试计算它包含多少个单词将使用方法split(),它根据一个字符串创建一个单词列表。下面是对只包含童话名"Alice in Wonderland"的字符串调用方法split()的结果:

>>> title = "Alice in Wonderland"
>>> title.split()
['Alice', 'in', 'Wonderland']

方法split()以空格为分隔符将字符串分拆成多个部分,并将这些部分都存储到一个列表中。结果是一个包含字符串中所有单词的列表,虽然有些单词可能包含标点。为计算Alice inWonderland包含多少个单词,我们将对整篇小说调用split(),再计算得到的列表包含多少个元素,从而确定整篇童话大致包含多少个单词:

filename = 'alice.txt'
try:
	with open(filename) as f_obj:
		contents = f_obj.read()
except FileNotFoundError:
	msg = "Sorry, the file " + filename + " does not exist."
	print(msg)
else:
	# 计算文件大致包含多少个单词
	words = contents.split()
	num_words = len(words)
	print("The file " + filename + " has about " + str(num_words) + " words.")

把文件alice.txt移到了正确的目录中,让try代码块能够成功地执行。对变量contents(它现在是一个长长的字符串,包含童话Alice in Wonderland的全部文本)调用方法split(),以生成一个列表,其中包含这部童话中的所有单词。
使用len()来确定这个列表的长度时,就知道了原始字符串大致包含多少个单词,

使用多个文件

下面多分析几本书。这样做之前,我们先将这个程序的大部分代码移到一个名为count_words()的函数中,这样对多本书进行分析时将更容易:

#word_count.py
def count_words(filename):
	"""计算一个文件大致包含多少个单词"""
	try:
		with open(filename) as f_obj:
		contents = f_obj.read()
	except FileNotFoundError:
		msg = "Sorry, the file " + filename + " does not exist."
		print(msg)
	else:
		# 计算文件大致包含多少个单词
		words = contents.split()
		num_words = len(words)
		print("The file " + filename + " has about " + str(num_words) +" words.")

filename = 'alice.txt'
count_words(filename)

这些代码大都与原来一样,只是将它们移到了函数count_words()中,并增加了缩进量。修改程序的同时更新注释是个不错的习惯,因此将注释改成了文档字符串,并稍微调整了一下措辞.

可以编写一个简单的循环,计算要分析的任何文本包含多少个单词了。为此,我们将要分析的文件的名称存储在一个列表中,然后对列表中的每个文件都调用count_words()。将尝试计算Alice in Wonderland、 Siddhartha、 Moby Dick和Little Women分别包含多少个单词,它们都不受版权限制。故意没有将siddhartha.txt放到word_count.py所在的目录中,让你能够看到这个程序在文件不存在时处理得有多出色

def count_words(filename):
	--snip--

filenames = ['alice.txt', 'siddhartha.txt', 'moby_dick.txt', 'little_women.txt']
for filename in filenames:
		count_words(filename)

文件siddhartha.txt不存在,但这丝毫不影响这个程序处理其他文件:

The file alice.txt has about 29461 words.
Sorry, the file siddhartha.txt does not exist.
The file moby_dick.txt has about 215136 words.
The file little_women.txt has about 189079 words

在这个示例中,使用try-except代码块提供了两个重要的优点:避免让用户看到traceback;让程序能够继续分析能够找到的其他文件。如果不捕获因找不到siddhartha.txt而引发的FileNotFoundError异常,用户将看到完整的traceback,而程序将在尝试分析Siddhartha后停止运行——根本不分析Moby Dick和Little Women。

失败时一声不吭

在前一个示例中,告诉用户有一个文件找不到。但并非每次捕获到异常时都需要告诉用户,有时候你希望程序在发生异常时一声不吭,就像什么都没有发生一样继续运行。要让程序在失败时一声不吭,可像通常那样编写try代码块,但在except代码块中明确地告诉Python什么都不要做。 Python有一个pass语句,可在代码块中使用它来让Python什么都不要做:

def count_words(filename):
	"""计算一个文件大致包含多少个单词"""
	try:
		--snip--
	except FileNotFoundError:
		pass
	else:
		--snip--

filenames = ['alice.txt', 'siddhartha.txt', 'moby_dick.txt', 'little_women.txt']
for filename in filenames:
	count_words(filename)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值