小甲鱼python听课笔记p31-p35 文件 & 泡菜pickle & 异常 & with
p31 7.9文件系统 (模块)
模块:
在使用某个函数的时候要引入这个模块,用import
模块是一个包含所有你定义的函数和变量的文件,其后缀名是.py。模块可以被别的程序引用,以使用该模块中的函数等功能
如:
Python是跨平台的语言,也即是说同样的源代码在不同的操作系统不需要修改就可以同样实现。因此Python的作者就倒腾了OS模块这么一个玩意儿出来,有了OS模块,我们不需要关心什么操作系统下使用什么模块,OS模块会帮你选择正确的模块并调用。
os模块中关于文件/目录常用的函数使用方法
函数名 |
使用方法 |
getcwd() |
返回当前工作目录 |
chdir(path) |
改变工作目录 |
listdir(path='.') |
列举指定目录中的文件名('.'表示当前目录,'..'表示上一级目录) |
mkdir(path) |
创建单层目录,如该目录已存在抛出异常 |
makedirs(path) |
递归创建多层目录,如该目录已存在抛出异常,注意:'E:\\a\\b'和'E:\\a\\c'并不会冲突 |
remove(path) |
删除文件 |
rmdir(path) |
删除单层目录,如该目录非空则抛出异常 |
removedirs(path) |
递归删除目录,从子目录到父目录逐层尝试删除,遇到目录非空则抛出异常 |
rename(old, new) |
将文件old重命名为new |
system(command) |
运行系统的shell命令 |
walk(top) |
遍历top路径以下所有的子目录,返回一个三元组:(路径, [包含目录], [包含文件])【具体实现方案请看:第30讲课后作业^_^】 |
以下是支持路径操作中常用到的一些定义,支持所有平台 |
|
os.curdir |
指代当前目录('.') |
os.pardir |
指代上一级目录('..') |
os.sep |
输出操作系统特定的路径分隔符(Win下为'\\',Linux下为'/') |
os.linesep |
当前平台使用的行终止符(Win下为'\r\n',Linux下为'\n') |
os.name |
指代当前使用的操作系统(包括:'posix', 'nt', 'mac', 'os2', 'ce', 'java') |
A文件、B文件如下:
os.path模块中关于路径常用的函数使用方法
函数名 |
使用方法 |
basename(path) |
去掉目录路径,单独返回文件名 |
dirname(path) |
去掉文件名,单独返回目录路径 |
join(path1[, path2[, ...]]) |
将path1, path2各部分组合成一个路径名 |
split(path) |
分割文件名与路径,返回(f_path, f_name)元组。如果完全使用目录,它也会将最后一个目录作为文件名分离,且不会判断文件或者目录是否存在 |
splitext(path) |
分离文件名与扩展名,返回(f_name, f_extension)元组 |
getsize(file) |
返回指定文件的尺寸,单位是字节 |
getatime(file) |
返回指定文件最近的访问时间(浮点型秒数,可用time模块的gmtime()或localtime()函数换算)使用time模块,要import time |
getctime(file) |
返回指定文件的创建时间(浮点型秒数,可用time模块的gmtime()或localtime()函数换算) |
getmtime(file) |
返回指定文件最新的修改时间(浮点型秒数,可用time模块的gmtime()或localtime()函数换算) |
以下为函数返回 True 或 False |
|
exists(path) |
判断指定路径(目录或文件)是否存在 |
isabs(path) |
判断指定路径是否为绝对路径 |
isdir(path) |
判断指定路径是否存在且是一个目录 |
isfile(path) |
判断指定路径是否存在且是一个文件 |
islink(path) |
判断指定路径是否存在且是一个符号链接 |
ismount(path) |
判断指定路径是否存在且是一个挂载点 |
samefile(path1, paht2) |
判断path1和path2两个路径是否指向同一个文件 |
文件创建时间:
课后练习:【啊啊啊啊我不想做了!!】
0.编写一个程序,统计当前目录下每个文件类型的文件数,程序实现如图:
p32 永久存储 (泡菜)
pickle模块
可以将列表、字典等复杂类型转换为二进制文件
pickling:存放
unpickling:读取
load()读取
使用时:
比如我做一个天气系统,我需要将每个城市对应的编码都事先写入到代码里,这样会导致整个代码很长很冗余,于是可以将城市对应的编码编写为一个泡菜放在代码外面,使用的时候调用就可以了。那么和文件的导入有什么区别?答,普通文件读取出的是字符串,而使用泡菜的话就不用考虑变量类型的问题。
注意pickle在倒入和读出的时候,对文件一定要用二进制形式,wb或rb(b就是二进制,w是写,r是读)
课后练习:
0.pickle的实质是什么?
答:pickle的实质就是利用一些算法将你的数据对象“腌制”成二进制文件,存储在磁盘上,当然也可以放在数据库或者通过网络传输到另一台计算机上。
1.使用pickle的什么方法存储数据?
答:pickle.dump(data, file) # 第一个参数是待存储的数据对象,第二个参数是目标存储的文件对象,注意要先使用'wb'的模式open文件哦。
0.编写一个程序,这次要求使用pickle将文件(record.txt)里的对话按照以下要求腌制成不同文件(没错,是第29讲的内容小改,考考你自己能写出来吗?
p33 异常处理1:exception 你不可能永远是对的
exception
比如打开一个文件:
当用户输入record的时候会出现错误,找不到这个文件,因为在用户眼里没有后缀名的概念,而输入record.txt就可以
python标准异常类型总结:
AssertionError |
断言语句(assert)失败 |
AttributeError |
尝试访问未知的对象属性 |
EOFError |
用户输入文件末尾标志EOF(Ctrl+d) |
FloatingPointError |
浮点计算错误 |
GeneratorExit |
generator.close()方法被调用的时候 |
ImportError |
导入模块失败的时候 |
IndexError |
索引超出序列的范围 |
KeyError |
字典中查找一个不存在的关键字 |
KeyboardInterrupt |
用户输入中断键(Ctrl+c) |
MemoryError |
内存溢出(可通过删除对象释放内存) |
NameError |
尝试访问一个不存在的变量 |
NotImplementedError |
尚未实现的方法 |
OSError |
操作系统产生的异常(例如打开一个不存在的文件) |
OverflowError |
数值运算超出最大限制 |
ReferenceError |
弱引用(weak reference)试图访问一个已经被垃圾回收机制回收了的对象 |
RuntimeError |
一般的运行时错误 |
StopIteration |
迭代器没有更多的值 |
SyntaxError |
Python的语法错误 |
IndentationError |
缩进错误 |
TabError |
Tab和空格混合使用 |
SystemError |
Python编译器系统错误 |
SystemExit |
Python编译器进程被关闭 |
TypeError |
不同类型间的无效操作 |
UnboundLocalError |
访问一个未初始化的本地变量(NameError的子类) |
UnicodeError |
Unicode相关的错误(ValueError的子类) |
UnicodeEncodeError |
Unicode编码时的错误(UnicodeError的子类) |
UnicodeDecodeError |
Unicode解码时的错误(UnicodeError的子类) |
UnicodeTranslateError |
Unicode转换时的错误(UnicodeError的子类) |
ValueError |
传入无效的参数 |
ZeroDivisionError |
除数为零 |
Python 内置异常类的层次结构:
BaseException
+-- SystemExit
+-- KeyboardInterrupt
+-- GeneratorExit
+-- Exception
+-- StopIteration
+-- ArithmeticError
| +-- FloatingPointError
| +-- OverflowError
| +-- ZeroDivisionError
+-- AssertionError
+-- AttributeError
+-- BufferError
+-- EOFError
+-- ImportError
+-- LookupError
| +-- IndexError
| +-- KeyError
+--MemoryError
+-- NameError
| +-- UnboundLocalError
+-- OSError
| +-- BlockingIOError
| +-- ChildProcessError
| +-- ConnectionError
| | +-- BrokenPipeError
| | +-- ConnectionAbortedError
| | +-- ConnectionRefusedError
| | +-- ConnectionResetError
| +-- FileExistsError
| +-- FileNotFoundError
| +-- InterruptedError
| +-- IsADirectoryError
| +-- NotADirectoryError
| +-- PermissionError
| +-- ProcessLookupError
| +-- TimeoutError
+-- ReferenceError
+-- RuntimeError
| +-- NotImplementedError
+-- SyntaxError
| +-- IndentationError
| +-- TabError
+-- SystemError
+-- TypeError
+-- ValueError
| +-- UnicodeError
| +-- UnicodeDecodeError
| +-- UnicodeEncodeError
| +-- UnicodeTranslateError
+-- Warning
+-- DeprecationWarning
+-- PendingDeprecationWarning
+-- RuntimeWarning
+-- SyntaxWarning
+-- UserWarning
+-- FutureWarning
+-- ImportWarning
+-- UnicodeWarning
+-- BytesWarning
+-- ResourceWarning
课后练习:
7.请问以下代码是否会产生异常,如果会的话,请写出异常的名称:
答:UnboundLocalError: local variable 'x' referenced before assignment.
闭包的知识大家还记得不? Python 认为在内部函数的 x 是局部变量的时候,外部函数的 x 就被屏蔽了起来,所以执行 x *= x 的时候,在右边根本就找不到局部变量 x 的值,因此报错。
在 Python3 之前没有直接的解决方案,只能间接地通过容器类型来存放,因为容器类型不是放在栈里,所以不会被“屏蔽”掉。
容器类型这个词儿大家是不是似曾相识?我们之前介绍的字符串、列表、元祖,这些啥都可以往里的扔的就是容器类型啦。
于是乎我们可以把代码改造为:
但是到了 Python3 的世界里,又有了不少的改进,如果我们希望在内部函数里可以修改外部函数里的局部变量的值,那么也有一个关键字可以使用,就是 nonlocal:
p34 异常处理2:你不可能永远是对的
检测和处理异常
检测异常 try语句
try – except语句:
语法:
举例:
这个程序会抛出异常:
于是可以用try – except语句进行修改:
运行之后就没有刚才那一长串报错
但是我们希望打印出出错的原因:
运行之后就可以打印出错原因:
try之后可以同时多个except:
运行后:
为什么没有之前的“文件出错…….和原因”呢?
因为python是解释性语言,他在运行到sum就出错了抛出异常,就没有再运行后面的了
如果我们的错误不在我们所写的except的类型里面:
比如int(abc)
会发现他就会变成老样子的错误:
try – finally语句:
语法:
举例:
运行了以下程序之后会在py文件当前目录新建一个“我为什么是一个文件.txt”文件
运行之后,返回一个5,就是输入了5个字
但是打开txt文件里面是空的,因为在运行到sum语句的时候就抛出了异常,所以文件f.close()并没有运行,就是文件并没有关闭,所以没有输入
所以可以用到finally语句,将我们必须要执行的语句放在这里面:
运行后:
raise语句:
代码自己抛出一个异常
课后练习:
2. 你知道如何统一处理多类异常吗?
答:在 except 后边使用小括号“()”把多个需要统一处理的异常括起来:
2.把文件关闭放在 finally 语句块中执行还是会出现问题,像下边这个代码,当前文件夹中并不存在"My_File.txt"这个文件,那么程序执行起来会发生什么事情呢?你有办法解决这个问题吗?
我们这么修正:
p35 丰富的else语句和简洁的with语句
else语句
if – else
while – else
with语句
这里是无法读出data文件中的内容的,因为没有内容,运行后出错:
下面改用with:
with语句抽象出了文件操作中频繁使用的try-except-finally语句等的相关细节:
- 在文件操作中使用with语句,可以大大的减少代码量
- 它会保证每次open完文件后都自动关闭文件
- 如果文件不存在,也不会关闭一个不存在的文件,而引起错误
课后练习:
0.使用 with语句改写以下代码,让 Python去关心文件的打开与关闭吧。
改为: