B站python入门学习---第一阶段第八~九章 文件操作、异常、模块与包

第八章 文件

一、文件的读取操作

文件操作主要包括:打开、关闭以及读和写。

#文件打开命令有三个参数
#第一个参数为文件路径,可以用相对路径,也可以是绝对路径
#第二个参数为模式参数,r表示只读,第三个参数为文件编码格式
f = open("test1.txt", "r", encoding="UTF-8")
#read()方法中可以设置一次性读取的字节数
print(f"读取两个字节的结果为{f.read(2)}")
#继续读取的话会从前面已读完的位置再继续开始
print(f"读取两个字节的结果为{f.read(2)}")
print(f"继续读取完毕的结果为{f.read()}")
#操作完成需要关闭文件
f.close()
#继续打开
f = open("test1.txt", "r", encoding="UTF-8")
#readlines()是按逐行读取的方式,内容逐行存储在列表中
lines = f.readlines()
for i in lines:
    print(i)
#操作完成关闭文件
#另外还有readline()方法,只读一行
f = open("test1.txt", "r", encoding="UTF-8")
print(f"第一次使用readline()读取结果为{f.readline()}")
print(f"第二次使用readline()读取结果为{f.readline()}")
print(f"继续使用readlines()读取结果为{f.readlines()}")
#结束记得关闭文件
f.close()

为避免忘记关闭文件,可以通过with open方式打开文件:

with open("test1.txt", "r", encoding="UTF-8") as f:
    #其实也可以直接用for lines in f,这种方式每次遍历也是得到一行数据
    for lines in f.readlines():
        print(lines)

小练习:

'''
读取指定文件内容
并统计itheima出现的次数
'''


with open("test2.txt", "r", encoding="UTF-8") as f:
    text = f.read()
    print(text)
    counter = text.count("itheima")
    print(f"itheima在文本中总共出现了{counter}次。")

二、文件的写入操作

#文件写入
#1、同样先打开文件,如果文件不存在,则新创建一个文件,并写入内容
#如果文件已存在,w模式会覆盖原有内容

f = open("test3.txt", "w", encoding="UTF-8")
#2、写入,实际这里是写在内存的
f.write("python learning!")

#3、刷新,将内存中内容刷新到文件中
f.flush()
#4、关闭文件,close()方法自带flush功能
f.close()

三、文件的追加操作

#文件追加
#1、同样先打开文件,如果文件不存在,则新创建一个文件,并写入内容
#如果文件已存在,a模式会在原有内容后面追加写入内容

f = open("test3.txt", "a", encoding="UTF-8")
f.write("\npython learning!222")
f.close()

综合案例

'''
    读取bill.txt文件
    将文件写出到bill.txt.bak文件,作为备份
    同时,将文件内标记为测试的数据正常丢弃
'''
f_resouce  = open("bill.txt", "r", encoding="UTF-8")
f_aim = open("bill.txt.bak", "w", encoding="UTF-8")
for line in f_resouce:
    if "测试" in line:
        continue
    f_aim.write(line)

f_resouce.close()
f_aim.close()

 

第九章  异常处理,模块和包

一、异常处理

之前学习到编程中异常处理的时候往往不是太明白,为何需要异常处理这个机制,多调试不就可以了么。现在看,这就是程序设计健壮性的体现,何况现在软件工程设计中大量的分工协作,你即便能保证你代码的完美,你不能确保你导入模块、函数等文件代码的完美,所以提供异常处理确实是一种程序健壮性的实现;另外一种情况,一段代码实现了N种功能,而我在某个时刻只关注其中一种功能的实现,但调试的时候总在其他部分出现BUG,那么也可以通过异常处理机制来暂时“屏蔽”或者代替这个BUG代码段。

'''
演示异常的处理
'''
#基本捕获语法
try:
    f = open("test_except.txt", "r", encoding="UTF-08")
except:
    print("出现异常了!")

一般来说,异常只处理逻辑类错误,语法类,比如多了个标点,少了括号等语法类错误,异常处理不适用:

#语法错误,会报错,无法异常处理
try:
    print("ABC"       #少一个括号
except:
    print("ERROR!")        

在知道某段代码可能出现BUG,而且大概率可以判断其异常类型的话可以指定异常种类,并通过as语句获取其更多信息。

#捕获指定异常
try:
    print(name)
except NameError as e:
    print("异常出现!")
    print(e)

try:
    print(1/0)
except ZeroDivisionError as e:
    print("异常出现!")
    print(e)

as之后的e对象是异常类的对象,其类型就是异常,但其实质内容就是之前的报错文本信息,可以通过str()转换为字符串格式(当然可以不转换,因为直接打印也可以显示)

try:
    print(1/0)
except ZeroDivisionError as e:
    print("异常出现!")
    print(f"出现了{type(e)}类异常,提示信息为{e}")
    print(str(e)+"135")    #除了可以直接打印之外,如要对e进行字符串操作需要先str转换

捕获各种异常类型的指定类型Exception

#捕获所有类型异常
try:
    1/0       #第一个除0异常
except Exception as e:
    print(f"出现了{type(e)}类的异常,提示信息为{e}")

如果不确定是某种类型,但知道是几种类型范围之内,可以如下处理:

#捕获多种类型的异常
try:
    name       #第一个除0异常
except (ZeroDivisionError, NameError) as e:
    print(f"出现了{type(e)}类的异常,提示信息为{e}")

除了try-except的形式,还可以通过else来提供没有异常情况下的处理代码,而finally则是无论异常是否发生都必须执行的代码

#else和finally的用法
try:
    f = open("test_exception.txt", "r", encoding="UTF-8")   #只读方式打开一个不存在的文件会产生异常
except Exception as e5:
    print(f"出现了{type(e5)}类的异常,提示信息为{e5}")
    f = open("test_exception.txt", "w", encoding="UTF-8")  #通过写入模式打开则会新建一个文件
else:
    print("没有异常出现!")     #没有异常出现情况下的代码
finally:
    print("无论有无异常都必须执行的代码放到finally中!")
    print(f.close())          #对于本例,无论异常是否发生,关闭文件操作都是必要的

 

异常的传递,其实就是指部分代码调用异常代码所在模块的情况

def func1():
    print("Function1 start...")
    num = 1/0                   #此处为异常源头
    print("Function2 finished.")

def func2():
    print("Function2 start...")
    func1()                        #此处调用异常所在代码块
    print("Function2 finished.")


def main():
    try:
        func2()                #此处继续调用“调用异常代码”的代码块
    except Exception as e:
        print("Error!")
        print(e)
    finally:
        print("All Finished!")

main()                  #函数执行时候捕捉和处理异常

 

二、模块和包

1、模块:Python中一个以.py结尾的文件就是一个模块,模块可以被其他代码引用,实现代码的复用;

2、包:存放模块的文件夹,Python3.3之前的版本,包中必须要包括__init__.py文件其他代码猜可以导入该包内模块,__init__.py文件一般提供导入操作时的一些执行功能,当然也可以为空文件;Python3.3开始__init__文件不是必须;

3、库:即为各类包的合集。

#从p1包中导入a,b两个模块,会先执行p1包中的__init__文件
from p1 import a, b
print(1)

#再分别打印导入包中模块内定义的变量
print(a.a)
print(b.b)

一般来说,模块内只做类、函数、变量的定义,示例mod.py文件内容如下:

s = "If Comrade Napoleon says it, it must be right."
a = [100, 200, 300]

def foo(arg):
    print(f'arg = {arg}')

class Foo:
    pass

上面的mod.py只做了定义,执行该代码只在内存空间中创建了上述对象,而并不会有结果输出;

有时候我们不光要定义,也要模块可以作为脚本执行,那么在代码中需要增加执行代码,如下:

s = "If Comrade Napoleon says it, it must be right."
a = [100, 200, 300]

def foo(arg):
    print(f'arg = {arg}')

class Foo:
    pass

#如下增加执行代码
print(s)
print(a)
foo("Tuesday")
x = Foo()
print(x)

但是当我们把这个文件当作一个模块,在其他文件中引用时,同样的结果会输出出来,这让不是我们需要的结果。比如:

import mod

print("This is main Function.")
print(mod.s)
print(mod.a)

如上代码先执行导入模块的时候会把模块代码先执行,再执行本模块内的代码,执行结果如下:

If Comrade Napoleon says it, it must be right.
[100, 200, 300]
arg = Tuesday
<mod.Foo object at 0x0000021A41067CB0>
This is main Function.
[100, 200, 300]
If Comrade Napoleon says it, it must be right.

这显然不是我们需要的效果,我们希望模块文件作为脚本时候可以独立执行,但如果作为被导入的模块使用它本身的操作代码可以不执行(但其定义的对象依然可以被导入使用),这就需要增加 __name__ == __main__的判断

如果成立,则说明模块被单独执行了,此时该模块的name值就是__main__,如果模块是被导入才执行,那它的模块name值就是其文件名。如下mod.py示例:

s = "If Comrade Napoleon says it, it must be right."
a = [100, 200, 300]

def foo(arg):
    print(f'arg = {arg}')

class Foo:
    pass

print(f"此时本模块的__name__为{__name__}。")

if __name__ == "__main__":
    print("Exuting as standalone script!")
    print(s)
    print(a)
    foo("Tuesday")
    x = Foo()
    print(x)

执行上述模块输出结果如下:

此时本模块的__name__为__main__。
Exuting as standalone script!
If Comrade Napoleon says it, it must be right.
[100, 200, 300]
arg = Tuesday
<__main__.Foo object at 0x000002937CC07CB0>

如果main.py导入mod.py,main文件如下:

import mod

print("This is main Function.")
print(mod.s)
print(mod.a)

执行结果如下:

此时本模块的__name__为mod。
This is main Function.
If Comrade Napoleon says it, it must be right.
[100, 200, 300]

 关于导入内容,在使用from X import Y格式的时候,如果Y表示为“*”,即表示导入X中所有模块/对象/变量等。这里的导入范围是可以在X模块中__all__列表设置的。

#本模块定义了三个对象:列表,字符串,函数。
#通过__all__设置from impot *情况下的可导入对象为mylist和myfunc
__all__ = ["mylist", "myfunc"]

mylist = [1, 2, 3]
mystr = "Hello S!"
def myfunc():
    print("This is a function named myfunc in module c.")

在外部模块导入上模块时的执行情况:

from p1.c import *

#因为p1.c模块中__all__的设置,可以访问mylist和myfunc
print(mylist)
myfunc()
#但不可以访问mystr,下句会报错
#print(mystr)

__all__的设置仅对from X import *的情况有作用,对于未列入__all__列表内的对象,仍然可以通过名称导入。

上述为from import *导入模块中对象的限定操作,对于包的导入,同样可以设置包内__init__文件内__all__来指定可导入的包内模块。

p1包中有__init__文件和a,b,c模块,其中__init__文件内容:

#设置p1包中__init__文件中的__all__来限定可通过from import *导入的模块
__all__ = ["a", "b"]
print("This is Package1.")

主程序代码如下:

#因为p1中__init__内部__all__参数的设置,下面导入代码只能导入p1中的a,b
from p1 import *

#可以正常访问p1下的a,b模块
print(a.a)
print(b.b)

#但无法使用p1下的c模块
#print(c.mylist)

*异常、模块、包:综合案例  自定义工具包

创建一个自定义包,名称为:my_utils

包内提供两个模块:

1、str_util.py模块(字符串相关工具):

  函数:str_reverse(s),接受传入字符串,将字符串反转返回

  函数:substr(s, x, y),按照下标x,y对字符串s进行切片

2、file_util.py模块(文件处理相关工具):

  函数:print_file_info(file_name),接受传入文件的路径,打印文件内容,如果文件不存在则捕获异常输出提示信息,通过finally关闭文件

  函数:append_to_file(file_name, data),接受文件路径以及传入数据,将数据追加写入到文件中

 

"""
str_util.py模块(字符串相关工具):
"""


def str_reverse(s):
    """
    接受传入字符串,将字符串反转返回
    """
    return s[::-1]

def substr(s, x, y):
    """
    按照下标x,y对字符串s进行切片
    """
    return s[x:(y+1)]

#测试代码
if __name__ == "__main__":
    print(str_reverse("ILOVEPython!"))
    print(substr("ILOVECHINA", 2, 9))

 

"""
file_util.py模块(文件处理相关工具):

  函数:print_file_info(file_name),

  函数:append_to_file(file_name, data)
"""

def print_file_info(file_name):
    """
    接受传入文件的路径,打印文件内容,如果文件不存在则捕获异常输出提示信息
    通过finally关闭文件
    """
    try:
        f = open(file_name, "r", encoding="UTF-8")
    except Exception as e:
        print(f"文件{file_name}不存在,报错信息为{e}。")
    else:
        print(f"文件内容为:\n{f.read()}")
        f.close()

def append_to_file(file_name, data):
    """
    接受文件路径以及传入数据,将数据追加写入到文件中
    :param file_name:
    :param data:
    :return:
    """
    f = open(file_name, "a", encoding="UTF-8")
    f.write(data)
    f.close()

 

posted @ 2025-09-04 20:13  tsembrace  阅读(9)  评论(0)    收藏  举报