Advertisement

Python编程:从入门到实践-第十章(笔记)

阅读量:

10.1 :从文件中读取数据

利用文本文件中的数据,在内存环境中进行处理是必要的前提条件。为了实现这一目标, 可以采取两种不同的方法: 一种是一次性加载整个文件的内容; 另一种则是采用逐行加载的方式完成数据处理.


10.1.1 : 读取整个文件

  • 函数open():接受一个参数:要打开的文件的名称;

  • 关键字with在不再需要访问文件后将其关闭;

获取该文件的所有内容,并将其存储为一个长字符串放在变量contents中;

复制代码
 with open('pi_digits.txt') as file_object:

    
     contents = file_object.read()
    
 print(contents)

使用rstrip()删除字符串末尾的空白;

复制代码
 with open('pi_digits.txt') as file_object:

    
     contents = file_object.read()
    
 print(contents.rstrip())

10.1.2:文件路径

稳定路径引导Python去搜索指定位置,并将该位置设为与当前运行中的程序文件所在目录相同的层级。

复制代码
 with open('text_files/pi_digits.txt') as file_object:

    
     contents = file_object.read()
    
 print(contents.rstrip())

该Python脚本引导Python程序进入位于文件夹python_work下的子文件夹text_files内,并用于在指定的.txt文件中进行查找。

提示:在显示文件路径时,请注意Windows系统采用反斜杠符号(\)而非传统的斜杠符号(/),但在代码编写中仍可灵活使用斜杠符号。


10.1.3 :逐行读取

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

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

使用rstrip():删除多余的空白行

复制代码
 filename = 'pi_digits.txt'

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

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

使用with代码块进行操作,并将文件pi_digits.txt的每一行读取后存储于一个列表中;之后,在与该代码块外部的位置输出该列表。

复制代码
 filename = 'pi_digits.txt'

    
  
    
 with open(filename) as file_object:
    
     # readlines:从文件中读取每一行,并将其存储在一个列表中
    
     lines = file_object.readlines()
    
  
    
 for line in lines:
    
     print(line.rstrip())

10.1.5 :使用文件的内容

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

复制代码
 filename = 'pi_digits.txt'

    
  
    
 with open(filename) as file_object:
    
     lines = file_object.readlines()
    
  
    
 # 创建一个变量pi_string,用于指向圆周率的值
    
 pi_string = ''
    
  
    
 # 使用一个循环将各行加入pi_string,并删除每行末尾的换行符;
    
 for line in lines:
    
     pi_string += line.rstrip()
    
  
    
 print(pi_string)
    
 print(len(pi_string))

使用strip 删除空格

复制代码
 filename = 'pi_digits.txt'

    
  
    
 with open(filename) as file_object:
    
     lines = file_object.readlines()
    
  
    
 # 创建一个变量pi_string,用于指向圆周率的值
    
 pi_string = ''
    
  
    
 # 使用一个循环将各行加入pi_string,并删除每行末尾的换行符;
    
 for line in lines:
    
     pi_string += line.strip()
    
  
    
 print(pi_string)
    
 print(len(pi_string))

10.1.6 :包含一百万位的大型文件

只打印到小数点后50位,以免终端为显示全部1 000 000位而不断滚动:

复制代码
 filename = 'pi_million_digits.txt'

    
  
    
 with open(filename) as file_object:
    
     lines = file_object.readlines()
    
  
    
 # 创建一个变量pi_string,用于指向圆周率的值
    
 pi_string = ''
    
  
    
 # 使用一个循环将各行加入pi_string,并删除每行末尾的换行符;
    
 for line in lines:
    
     pi_string += line.strip()
    
  
    
 print(f"{pi_string[:52]}...")
    
 print(len(pi_string))

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

复制代码
 filename = 'pi_million_digits.txt'

    
  
    
 with open(filename) as file_object:
    
     lines = file_object.readlines()
    
  
    
 # 创建一个变量pi_string,用于指向圆周率的值
    
 pi_string = ''
    
  
    
 # 使用一个循环将各行加入pi_string,并删除每行末尾的换行符;
    
 for line in lines:
    
     pi_string += line.strip()
    
  
    
 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.")

10.2 : 写入文件

保存数据的最简单的方式之一是将其写入文件中;


10.2.1 :写入空文件

编写到目标文件中;在调用open函数时必须提供另一个参数,并告知Python程序要打开并写入该文件

复制代码
 filename = 'programming.txt'

    
 # 调用open时,提供了两个实参。第一个实参也是要打开的文件的名称;
    
 # 第二个参数 'w'告诉python,要以写入模式 打开这个文件;
    
 with open(filename, 'w') as file_object:
    
     # write():将一个字符串写入文件;
    
     file_object.write("I love programming.")

打开文件时候,可指定读取模式( ' r ' )、写入模式( ' w ' )、附加模式( ' a ' )或

读写模式( ' r + ' )。 如果省略了模式参数,python将以默认的只读模式打开文件;


10.2.2 : 写入多行

函数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')

运行结果:

I love programming.
I love creating new games.


10.2.3 : 附加到文件

若需为文件新增内容,则应采取附加模式来打开该文件。

对write_message.py进行优化,在现有文件programming.text中增添一些重要理由。

复制代码
 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")

运行结果:

I am deeply passionate about programming.
I relish crafting new games.
I also cherish discovering significance within vast amounts of data.
I am skilled at creating seamless applications that integrate perfectly with web browsers.

实参 ' a ' ,以便将内容附加到文件末尾,而不是覆盖文件原来的内容;


10.3 : 异常

python使用称为异常 的特殊对象来管理程序执行期间发生的错误;


10.3.1 处理ZeroDivisionError异常

例子:一种导致Python引发异常的简单错误;

复制代码
    print(5/0)

运行结果:

堆栈跟踪记录显示最近一次调用时发生了错误。在文件division_calculator.py中,在模块级别的第1行执行print语句时触发了该错误。具体来说,在尝试执行5除以0的操作时出现了ZeroDivisionError错误。

上述traceback中指出的错误ZeroDivisionError是个异常对象


10.3.2 : 使用try-except代码块

当预计可能发生错误时, 可以编写一个try-except代码块来处理可能出现的异常情况。

例如:

复制代码
 try:

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

为了使出现错误的代码行print(5/0)包含在一个try语句中,请在相应的try括号中放入这段可能引发除以零错误的打印操作。当尝试执行该尝试时若不会发生错误则Python会跳过对应的except语句;而当遇到除以零等运算时Python会触发异常机制并切换至相应的处理机制以避免程序崩溃。


10.3.3 :使用异常避免崩溃

例子:创建一个只执行除法运算的简单计算:

复制代码
 print("Give me two numbers and I'll divide them.")

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

运行结果:它将崩溃;

Request two numbers, and I will divide them.

Please enter 'q' to quit.

What is the first number?

What is the second number?

Traceback (most recent call last):


10.3.4 :else代码块

有效手段将潜在会导致错误出现的代码模块放置于try-except代码块中能够显著提升程序在面对错误时的抗性能力

try-except-else代码块的工作原理大致例子如下:

复制代码
 print("Give me two numbers and I'll divide them.")

    
 print("Enter 'q' to quit")
    
  
    
 while True:
    
     first_number = input("\nFirst number: ")
    
     if first_number == 'q':
    
     break
    
     second_number = input("Second 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)

运行结果:

请提供两个数字,并将它们相除。
按字母键 q 来退出程序
第一个数字:5
第二个数字:0
无法使用零作为除数!


10.3.5 :处理FileNotFundError异常

在使用文件时经常遇到的问题是无法找到所需的文档。这些文档可能存放在其他位置,并且还可能存在格式错误或者根本无法获取的情况。为了更好地应对这些问题,在编程中可以通过尝试-捕获代码块能够有效地解决问题。

例如:尝试读取一个不存在的文件;

复制代码
 filename = 'alice.text'

    
  
    
 with open(filename, encoding = 'utf-8') as f:
    
     contents = f.read()

运行结果:python无法读取不存在的文件,因此异常;

异常堆栈跟踪如下(最近的调用开始):
在Python脚本main.py中第3行,在模块导入时发现
使用open函数打开文件时指定编码参数为'utf-8'
文件不存在错误提示了:[错号2] 没有找到文件或目录:'alice.text'

处理这个错误,必须将try语句放在包含open()的代码行之前:

复制代码
 filename = 'alice.text'

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

运行结果:

Sorry, the file alice.text does not exist.


10.3.6 : 分析文本

split函数使用空格作为分割符来处理输入字符串,并将其切割后的小块数据全部存入列表中

复制代码
 title = "Alice in Wonderland"

    
 print(title.split())

运行结果:

['Alice', 'in', 'Wonderland']

为了统计alice.txt中的单词数量,我们计划使用Python中的split函数来分割文本,并随后统计生成的列表中有多少项以确定大致的单词数量。

复制代码
 filename = 'alice.txt'

    
  
    
 try:
    
     with open(filename, encoding='utf-8') as f:
    
     contents = f.read()
    
 except FileNotFoundError:
    
     print(f"Sorry, the file {filename} does not exist.")
    
 else:
    
     # 计算该文件大致包含多少个单词;
    
     words = contents.split()
    
     num_words = len(words)
    
     print(f"The file {filename} has about {num_words} words.")

运行结果:

The file alice.txt has about 29465 words.


10.3.7 :使用多个文件

复制代码
 def count_words(filename):

    
     """计算一个文件大致包含多少个单词"""
    
     try:
    
     with open(filename, encoding='utf-8') as f:
    
         contents = f.read()
    
     except FileNotFoundError:
    
     print(f"Sorry, the file {filename} does not exist.")
    
     else:
    
     words = contents.split()
    
     num_words = len(words)
    
     print(f"The file{filename} has about {num_words} words.")
    
  
    
  
    
 filenames = ['alice.txt', 'siddhartha.txt', 'moby_dick.txt', 'little_women.txt']
    
 for filename in filenames:
    
     count_words(filename)

运行结果:

Document alice.txt contains approximately 29,465 words.
Document Siddhartha.txt contains approximately 42,172 words.
Document Moby-Dick.txt contains approximately 215,830 words.
Document little_women.txt contains approximately 189,079 words.


10.3.8 静默失败

采用pass语句,在错误发生时也不会显示traceback并不会产生任何输出信息,同时也可以作为占位符使用。

复制代码
 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"The file{filename} has about {num_words} words.")
    
  
    
  
    
 filenames = ['alice.txt', 'siddhartha.txt', 'moby_dick.txt', 'little_women.txt']
    
 for filename in filenames:
    
     count_words(filename)

10.4 :存储数据

采用Python库json将数据导出至文件中,并在程序重新执行时导入该文件中的数据。此外,在不同Python程序之间传输数据也可以利用JSON格式实现。

JSON(JavaScript Object Notation)


10.4.1 : 使用json.dump () 和json.load ()

使用函数json.dump () 将数字列表存储到文件numbers.json中;

复制代码
 import json

    
 numbers = [2, 3, 5, 7, 11, 13]
    
  
    
 # 指定了要该数字列表存储到那个文件中,通常使用.jason格式存储;
    
 filename = 'numbers.json'
    
 with open(filename, 'w') as f:
    
     # 函数json.dump()将数字列表存储到文件numbers.jason;
    
     json.dump(numbers, f)

使用json.load()将列表读取到内存中:

复制代码
 import json

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

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

指导用户在初次启动程序时要求其提供个人名称,并确保该信息在后续启动中被保留。

复制代码
 import json

    
 username = input('what is your name? ')
    
  
    
 filename = 'username.json'
    
 with open(filename, 'w') as f:
    
     json.dump(username, f)
    
     print(f"We'll remember you when you come back, {username}! ")

再编写一个程序,向已存储了名字的用户发出问候:

复制代码
 import json

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

将以上两个程序整合到一个程序(remeber_me.py)中,并命名为remeber_me.py;随后进一步读取username.json文件中的信息。

复制代码
 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'll remember you when you come back, {username}!")
    
  
    
 else:
    
     print(f"Welcome back, {username}!")

10.4.3 :重构

重构让代码更清晰、更易于理解、更容易扩容。

要重构remember_me.py,可将其大部分逻辑放到一个或多个函数中;

例子:

复制代码
 import json

    
 def greet_user():
    
     """问候用户,并指出其名字"""
    
     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.dum(username, f)
    
         print(f"We'll remember you when you come back, {username}!")
    
     else:
    
     print(f"Welcome back, {username}!")
    
  
    
 greet_user()

下面来重构greet_user()的功能模块, 降低其工作量. 为此目的, 首先将获取已存储用户的代码部分独立提取到另一个辅助函数中进行处理.

复制代码
 import json

    
  
    
 def get_stored_username():
    
     """如果存储了用户名,就获取它"""
    
     filename = 'username.json'
    
     try:
    
     with open(filename) as f:
    
         username = json.load(f)
    
     except FileNotFoundError:
    
     # 如果文件username.json不存在则返回None, 反之返回username
    
     return None
    
     else:
    
     return username
    
  
    
 def greet_user():
    
     """问候用户,并指出其名字"""
    
     username = get_stored_username()
    
     if username:
    
     print(f"Welcome back, {username}!")
    
     else:
    
     username = input("What is your name? ")
    
     filename = 'username.json'
    
     with open(filename, 'w') as f:
    
         json.dump(username,f)
    
         print(f"We'll remember you when you come back, {username}!")
    
  
    
 greet_user()

另外需要重构greet_uer内部的另一部分代码,在未存储用户名的情况下提示用户输入验证码作为单独的功能模块。

复制代码
 import json

    
  
    
 def get_stored_username():
    
     """如果存储了用户名,就获取它"""
    
     filename = 'username.json'
    
     try:
    
     with open(filename) as f:
    
         username = json.load(f)
    
     except FileNotFoundError:
    
     return None
    
     else:
    
     return username
    
  
    
  
    
 def get_new_username():
    
     """提示用户输入用户名"""
    
     username = input('what is your name? ')
    
     filename = 'username.json'
    
     with open(filename, 'w') as f:
    
     json.dump(username, f)
    
     return username
    
  
    
  
    
 def greet_user():
    
     """问候用户,并指出其名字"""
    
     username = get_stored_username()
    
     if username:
    
     print(f"Welcome back, {username}!")
    
     else:
    
     username = get_stored_username()
    
     print(f"We'll remember you when you come back, {username}! ")
    
  
    
  
    
 greet_user()

全部评论 (0)

还没有任何评论哟~