Python编程:文件和异常

1.从文件中读取数据

        文本文件可以储存大量的数据,如果我们要使用文本文件的信息,就必须将这些信息读取到内存中。为此,我们可以一次性读取全部内容,也可以逐行读取。

1.1读取整个文件

        要读取文件,首先你得知道文件的位置。然后通过下段代码进行读取:

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

print(contents)

        函数open()是用来打开文件,它接受一个参数:要打开文件的名称。然后,Python会在当前文件夹所在的目录中查找指定文件。当然,这里涉及到相对路径和绝对路径的问题,我们后边再说。

        关键字with在不再需要访问文件后将其关闭。注意,我们在上段代码中调用了函数open,但并未调用函数close,这是因为我们通常不确定何时要关闭文件,使用关键字with,让Python在合适的时机自己关闭文件。

        当读取到文本文件中的信息后,使用方法read()读取这个文件的全部内容,并将其作为字符串赋值给变量contents。但是在打印结果时,我们会发现多了一个空白行。这时,我们可以在print()使用rstrip()来删除末尾的空白行。

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

print(contents.rstrip())

1.2文件路径

        将类似于'pi_digits.txt'的简单文件名传递给函数open时,Python会在当前执行文件所在的目录中查找。

        如果文本文件不在当前执行文件所在的目录,可以考虑使用相对目录(推荐使用)和绝对目录。如果要打开的文本文件所在的文件夹在当前的目录中,使用相对路径会比较简单。可以使用以下代码来调用。

with open('text_files/filename.txt') as file_object:

        如果所需的文本文件不在当前文件夹所在目录下,就考虑使用绝对路径。通常绝对路径会比较长,因此要将它赋值给一个变量,再将这个变量作为参数传递给函数open。使用绝对路径可以访问系统中任何地方的文件。

file_path = '/home/ehmatthes/other_files/text_files/filename.txt'
with open(file_path) as file_object:

1.3逐行读取

        读取文件,常常需要检查其中的每一行,要以每次一行的方式检查文件,可以使用for循环。

filename = 'pi_digits.txt'

with open(filename) as file_object:
    for line in file_object:
        print(line)

        这样打印出来时,会发现每一行都多了空行,可以在print()中使用rstrip()来删除末尾的空白行。

filename = 'pi_digits.txt'

with open(filename) as file_object:
    for line in file_object:
        print(line.rstrip())

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

        使用关键字with时,函数open返回的文件对象只能在with代码块中使用。如果要在with代码段外使用文件中的内容,可以在with代码块内将内容存储到一个列表中。这样,调用该列表就可以使用文件中的内容了。

filename = 'chapter_10/pi_digits.txt'

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

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

        方法readlines()从文件中读取每一行,并将其存储到一个列表中。在上段代码中,将列表赋给变量lines了。

1.5使用文件中的内容

        将文件的内容读取到内存后,就可以在任何地方使用该内容了。

filename = 'chapter_10/pi_digits.txt'

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

pi_string = ''
for line in lines:
    pi_string += line.rstrip()

print(pi_string)
print(len(pi_string))

        运行上述代码段,会发现在每行数据前多了空格,这是我们需要用方法strip()来删除每行左边的空格。

filename = 'chapter_10/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))

        注意,Python读取文本文件时,会将所有的数据类型都解读为字符串。如果想要读取数据,并将其作为数值来使用,就必须使用函数int()和float()来将其转化为数据类型。

1.6包含百万位的大文件

        读取文本文件时,我们不免会遇到一些大的文本文件。但不要害怕,我们像之前处理小的文本文件那样处理它即可。

filename = 'chapter_10/pi_million_digits.txt'

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

pi_million_string = ''
for line in lines:
    pi_million_string += line.strip()

print(pi_million_string[:52])
print(len(pi_million_string))

        在打印数据时,我们使用了切片,只打印了小数点后50位。这是因为位数过多的话终端显示时,数据会不断滚动。

2.写入文件

        保存数据最简单的方式之一就事件数据保存到txt文件中去。

2.1写入空文件

        要将文本写入文件,在调用函数open()时需要提供另外一个实参,告诉Python你要写入打开的文件。下面是一个简单的例子:

filename = 'programming.txt'

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

        在本例子中,调用函数open()时提供了两个参数,第一个参数是要打开文件的名称,第二个参数是你要以什么模式打开文件。打开文件时,你可以指定下面四种模式:

        读取模式(‘r’):可以读取文件中的信息。

        写入模式(‘w’):清空文件原有信息,然后在写入要输入的信息。

        附加模式(‘a’):在原文件的末尾,写入要输入的信息。

        读写模式(‘r+’):即以读取和写入模式打开文件。

       要注意,如果忽略了第二个参数,就默认以只读的方式打开文件,如果第一个参数所指定的文件夹不存在,系统会默认建立它,并写入数据。还有,就是Python只能将字符串写入文件,如果要将数值数据写入文件,要先用str()将数值数据转化为字符串,再写入文件。

2.2写入多行

        函数write()不会在写入文本的末尾添加换行符,如果要写入多行数据,要注意在函数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 game.\n")

2.3附加文件

        给文件添加内容,而不是要将文件原有的内容清空,可以使用附加模式。若给定的文件不存在,则创建该文件并写入数据。如果该文件存在,则在该文件的行末尾添加要写入的信息。

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.\n")

3.异常

        Python使用称为异常的特殊对象来管理程序执行期间发生的错误。每当Python发生错误时,它都会创建一个异常对象。如果你编写了处理该异常的文件,程序将继续运行,如果没有编写,程序将停止运行,并显示traceback。

        异常是使用try-except代码块来处理的。try-except代码块让Python执行指定的操作,并且告诉Python出现异常时,要如何处理。

3.1处理ZeroDivisionError异常

        当用一个数除以0时,就会触发该异常。

3.2使用try-except代码块

        当你认为程序可能会出现错误时,可以使用try-except代码块来处理可能引发的异常。

try:
    print(5/0)
except ZeroDivisionError:
    print("You can't divide by zero!")

3.3使用异常避免程序崩溃

        发生错误时,如果程序还没有运行完,妥善的处理错误尤为重要,这影响到你程序之后的运行。

print("Give me two numbers, and I will divide them!")
print("Enter 'q' to quit.")

while True:
    first_number = input("\nFirst number")
    if first_number == 'q':
        break
    second_number = input("\nSecond number")
    if second_number == 'q':
        break
    answer = int(first_number)/int(second_number)
    print(answer)

        上段代码中,就未设置异常处理,当second_number输入0时,程序就会崩溃。所以要进行异常处理。

3.4使用else代码块

        通过将可能引发错误的代码放在try-except代码块中,可以有效地避免程序的崩溃,并且可以返回一个友好的错误。

print("Give me two numbers, and I will divide them!")
print("Enter 'q' to quit.")

while True:
    first_number = input("\nFirst number")
    if first_number == 'q':
        break
    second_number = input("\nSecond number")
    if second_number == 'q':
        break
    try:
        answer = int(first_number)/int(second_number)
    except ZeroDivisionError:
        print("You can't divide by 0")
    else:
        print(answer)

       try-except-else代码块工作原理如下,try中执行相关代码,如果出现异常执行except中代码,如果未发生异常,执行else中的代码。

3.5处理FileNotFoundError异常

        使用文件时,一种常见的错误就是找不到文件。对于这种错误,我们也可以使用 try-except-else代码块进行异常处理。

filename = 'alice.txt'

try:
    with open(filename, encoding='utf-8') as f:
        contents = f.read()
except FileNotFoundError:
    print(f"Sorry, the file {contents} is not exist!")

        本例在调用函数open()时,第二个是给参数encoding指定了值,在系统默认的编码与要读取文件的编码不一致时,必须要这样做。另外,使用了变量f来表示文件对象,这是一个常见的做法。

3.6分析文本

        你可以分析包含整本书的文本文件,当然你还可以分析其它的文件,本文以此为例。

filename = 'chapter_10/alice.txt'

try:
    with open(filename, encoding='utf-8') as f:
        contents = f.read()
except FileNotFoundError:
    print(f"Sorry, the file {filename} is not exist!")
else:
    # 计算文本中有多少单词
    words = contents.split()
    num_words = len(words)
    print(num_words)

        上段代码中,我们使用了方法split(),它能根据字符串创建一个单词的列表。该方法以空格为分隔符将字符串分割成多个部分,并将这些部分都储存到一个列表中。

3.7使用多个文件

        当要读取多个文件中的信息时,我们可以把文件名做成一个列表,利用for循环依次读取其中的信息,并进行处理。当眼,我们也可以把计算单词的数量的代码写成一个函数,方便调用。

def count_words(filename):
    """计算一个文件中有多少单词"""
    try:
        with open(filename, encoding='utf-8') as f:
            contents = f.read()
    except FileNotFoundError:
        print(f"Sorry, the file {filename} is not exist!")
    else:
        """计算文本中有多少单词"""
        words = contents.split()
        num_words = len(words)
        print(f"{filename} has about {num_words} words")

filenames = ['chapter_10/alice.txt', 'chapter_10/siddhartha.txt', 'chapter_10/moby_dick.txt', 'chapter_10/little_women.txt']

for filename in filenames:
    count_words(filename)

3.8静默失败

       在上段代码中,我们告诉用户有一个文件找不到。但是并非每次都要告知用户出现了异常,有时候我们希望程序在遇到异常时保持静默,就像没遇到一样继续正常运行。这时,我们要用到pass语句。

def count_words(filename):
    """计算一个文件中有多少单词"""
    try:
        with open(filename, encoding='utf-8') as f:
            contents = f.read()
    except FileNotFoundError:
        pass
    else:
        """计算文本中有多少单词"""
        words = contents.split()
        num_words = len(words)
        print(f"{filename} has about {num_words} words")

filenames = ['chapter_10/alice.txt', 'chapter_10/siddhartha.txt', 'chapter_10/moby_dick.txt', 'chapter_10/little_women.txt']

for filename in filenames:
    count_words(filename)

       当遇到异常时,会执行pass语句,即发生异常后,什么也不会发生,程序会继续正常运行。用户不会看到任何有关异常的信息。

       当然,我们要根据用户的需要以及自身的需求,合理的决定要报告哪些信息。

4.存储数据

        我们在要求用户输入一些数据后,有时需要存储这些数据,这时就要用到json模块,它能让你将数据结构存储到文件中,并在程序运行时再次加载数据。

4.1使用json.dump()和json.load()方法

        下面将写两个简单的例子来存储和导入文件中的数据。

#写入json数据
import json

numbers = [2, 3, 5, 7, 11, 13]

filename = 'numbers.json'
with open(filename, 'w') as f:
    json.dump(numbers, f)
#导入数据
import json

filename = 'numbers.json'
with open(filename) as f:
    numbers = json.load(f)

print(numbers)

        上面的代码中,导入了json模块,在将数据存储到文件中时,文件名的后缀要改成.json格式,表示你要以json形式存储数据。然后,调用了方法json.dump(),第一个参数是要存储的数据,第二个参数是你要将数据写入到那个文件中。在将数据导入到Python中时,同样先是导入json模块,然后指定一个要导入数据的文件,在使用json.load(打开文件时指定的别名)将文件中的数据导入,在赋值给一个变量即可。

4.2保存和读取用户生成的数据

        使用json来保护用户生成的数据是很有效果的。下面是一个例子。

import json

username = input("What's youe name?")

filename = 'username.json'
with open(filename, 'w') as f:
    json.dump(username, f)
    print(f"We'll remember you,{username}!")

with open(filename) as f:
    username = json.load(f)
    print(f"Welcome back, {username}!")

        当然,上段代码有许多瑕疵,下面进行改进,运用了try-except-else代码块。

import json

#如果以前存储了用户名,就加载它
#否则,提示用户输入用户名并存储他。
filename = 'username.json'
try:
    with open(filename) as f:
        username = json.load(f)
except FileNotFoundError:
    username = input("What is your name!")
    with open(filename, 'w') as f:
        json.dump(username, f)
        print(f"We will remember you ,{username}!")
else:
    print(f"Welcome back, {username}!")

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值