一、异常
1、异常的概念
在程序运行时,Python解释器遇到错误就会停止执行,并提示一些错误信息,这就是异常,我们称这个动作为抛出(raise)异常
程序开发时,很难将 所有的特殊情况 都处理的面面俱到,通过 异常捕获 可以针对突发事件做集中的处理,从而保证程序的 稳定性和健壮性
捕获异常:
try:
尝试执行的代码
except:
出现错误的处理
try: num = int(input("输入一个整数:")) print(num) except: print("请输入整数!")
2、错误类型捕获
try: # 尝试执行的代码 pass except 错误类型1: # 针对错误类型1,对应的代码处理 pass except (错误类型2, 错误类型3): # 针对错误类型2 和 3,对应的代码处理 pass except Exception as result: print("未知错误 %s" % result)
try: num = int(input("请输入整数:")) result = 8/num print("计算结果:%.2f" % result) except ValueError: print("请输入正确的整数") except ZeroDivisionError: print("除0错误") except Exception as result: print("未知错误 %s" % result)
3、异常捕获完整语法
try: # 尝试执行的代码 pass except 错误类型1: # 针对错误类型1,对应的代码处理 pass except 错误类型2: # 针对错误类型2,对应的代码处理 pass except (错误类型3, 错误类型4): # 针对错误类型3 和 4,对应的代码处理 pass except Exception as result: # 打印错误信息 print(result) else: # 没有异常才会执行的代码 pass finally: # 无论是否有异常,都会执行的代码 print("无论是否有异常,都会执行的代码")
else
只有在没有异常时才会执行的代码
finally
无论是否有异常,都会执行的代码
4、异常的传递
异常会传递给函数的调用一方,直到传递到主程序,如果仍没有异常处理,程序会被终止;
开发时可以在主程序中增加异常捕获,这样其他函数的异常都会传递到主程序,保证代码简洁;
def demo1(): return int(input("请输入整数:")) def demo2(): demo1() try: demo2() except ValueError: print("输入的不是整数!") except Exception as result: print("未知错误 %s" % result)
5、主动raise异常
Python
中提供了一个 Exception
异常类
在开发时,如果满足 特定业务需求时,希望 抛出异常,可以:
创建 一个 Exception
的 对象
使用 raise
关键字 抛出 异常对象
def input_password(): pwd = input("输入密码:") if len(pwd) >= 8: return pwd # 密码小于8位,抛出异常 # 1.创建异常对象 ex = Exception("密码长度不够") # 2.主动抛出异常 raise ex try: print(input_password()) except Exception as result: print("出现错误:%s" % result)
二、模块和包
1、模块导入
模块的扩展名以py结尾,模块名是一个标识符,在模块中定义的全局变量、类、函数都是给外界直接使用的工具;
(1)import导入:每个导入应单独占一行,导入后通过 模块名. 使用模块提供的工具
import 模块名1 import 模块名2
如果模块的名字太长,可以使用as指定模块的别名,模块别名应该符合大驼峰命名法
import d06_测试模块1 as Demo1 import d07_测试模块2 as Demo2 print(Demo1.gl_num) print(Demo2.title) Demo1.say_hello() Demo2.say_hello() dog = Demo1.Dog() cat = Demo2.Cat() print(dog) print(cat)
(2)from import导入:希望从某个模块中,导入部分工具
from 模块名 import 工具名
导入之后,可以直接使用模块提供的工具,不需要通过 模块名.
from d06_测试模块1 import Dog, say_hello from d07_测试模块2 import Cat say_hello() dog = Dog() cat = Cat()
如果两个模块存在同名的函数,后导入的模块,会覆盖掉先导入的函数;
开发时把import统一写在代码顶部,更容易及时发现冲突;
一旦发现冲突,可以使用as关键字给其中一个工具起个别名;
from d06_测试模块1 import Dog, say_hello from d07_测试模块2 import Cat, say_hello as say
2、模块的搜索顺序
Python
的解释器在 导入模块 时,会:
(1)搜索 当前目录 指定模块名的文件,如果有就直接导入
(2)如果没有,再搜索 系统目录
在开发时,给文件起名,不要和 系统的模块文件 重名
可以使用模块的内置属性__file__查看模块的完整路径
import random print(random.__file__)
3、模块的测试
在导入文件时,文件中 所有没有任何缩进的代码 都会被执行一遍
在实际开发中,每一个模块都是独立开发的,大多由专人负责,开发人员通常会在模块下方增加一些测试代码;
__name__
属性可以做到,测试模块的代码只在测试情况下被运行,而在 被导入时不会被执行!
__name__
是 Python
的一个内置属性,记录着一个字符串:
如果 是被其他文件导入的,__name__
记录的就是模块名
如果 是当前执行的程序__name__
是 __main__
def say_hello(): print("hello") # 测试模块的代码只在测试情况下被执行 # 在别的文件导入时,__name__的值为模块名,因此不会被执行 if __name__ == "__main__": print("yzz开发的模块") print(__name__) say_hello()
# 导入模块 # 定义全局变量 # 定义类 # 定义函数 # 在代码的最下方 def main(): # ... pass # 根据 __name__ 判断是否执行下方代码 if __name__ == "__main__": main()
4、包
包是包含多个模块的特殊目录;
目录下有一个特殊的文件__init__.py
包名与变量名一致,用小写字母和_命名
使用 import 包名 可以一次性导入包中所有模块
要在外界使用 包 中的模块,需要在 __init__.py
中指定 对外界提供的模块列表
yzz_message包:
send_message
def send(text): print("正在发送 %s ..." % text)
receive_message
def receive(): return "这是来自10088的短信..."
__init__.py
# .表示当前目录 from . import send_message from . import receive_message
主程序:
import yzz_message yzz_message.send_message.send("hello") txt = yzz_message.receive_message.receive() print(txt)
5、发布模块
希望自己开发的模块分享给他人,可以按以下步骤。
制作发布压缩包步骤:
(0)目录结构
--yzz_message
--send_message
--receive_message
--setup.py
(1)创建setup.py
from distutils.core import setup setup(name="hm_message", # 包名 version="1.0", # 版本 description="itheima's 发送和接收消息模块", # 描述信息 long_description="完整的发送和接收消息模块", # 完整描述信息 author="itheima", # 作者 author_email="itheima@itheima.com", # 作者邮箱 url="www.itheima.com", # 主页 py_modules=["hm_message.send_message", "hm_message.receive_message"])
有关字典参数的详细信息,可以参阅官方网站:https://docs.python.org/2/distutils/apiref.html
(2)构建模块
打开终端,进入项目目录
$ python3 setup.py build
(3)生成发布压缩包
$ python3 setup.py sdist
注意:要制作哪个版本的模块,就使用哪个版本的解释器执行!
安装模块:
在哪个目录下解压缩都可以
$ tar -zxvf hm_message-1.0.tar.gz
$ sudo python3 setup.py install
自动安装在 /usr/local/lib/python3.5/dist-packages/ 目录下
在程序中直接使用import,就可以导入安装好的模块啦
卸载模块:
可以使用 模块名.__file__ 查看包的完整路径
直接从安装目录下,把安装模块的 目录 删除就可以
$ cd /usr/local/lib/python3.5/dist-packages/
$ sudo rm -r hm_message*
6、pip安装第三方模块
第三方模块通常是指由知名的第三方团队开发的并且被程序员广泛使用的 Python
包 / 模块
pip
是一个现代的,通用的 Python
包管理工具,提供了对 Python
包的查找、下载、安装、卸载等功能
安装和卸载命令如下:
# 将pygame模块安装到 Python 2.x 环境 $ sudo pip install pygame $ sudo pip uninstall pygame # 将pygame模块安装到 Python 3.x 环境 $ sudo pip3 install pygame $ sudo pip3 uninstall pygame
在Linux下安装ipython:
$ sudo apt install ipython
$ sudo apt install ipython3
三、文件
1、文件的概念
计算机中的文件,就是存储在某种长期存储设备(硬盘 U盘 光盘)上的一段数据;
文件是以二进制的方式保存在磁盘上的;
文本文件:可以使用文本编辑软件查看,本质上还是二进制文件,例如:python 的源程序
二进制文件:
保存的内容不是给人直接阅读的,而是
提供给其他软件使用的,
例如:图片文件、音频文件、视频文件等等。
二进制文件不能使用文本编辑软件查看。
2、文件操作
open:打开文件,并且返回文件操作对象
read:将文件内容读取到内存
write:将指定内容写入文件
close:关闭文件
read write close三个方法都要通过文件对象来调用
3、读取文件
open函数的第一个参数是要打开的文件名,如果文件存在,返回文件操作对象,如果文件不存在,会抛出异常;
read方法可以一次性读入并返回文件的所有内容;
(read方法执行后,会把文件指针移动到文件的末尾,第一次读取之后,文件指针移动到了文件末尾,再次调用不会读取到任何的内容)
close方法负责关闭文件,如果忘记关闭文件,会造成系统资源消耗,而且会影响到后续对文件的访问;
file = open("README") txt = file.read() print(txt) file.close()
4、打开文件的方式
open函数默认以只读方式打开文件;
f = open("文件名", "访问方式")
r | 以只读方式打开文件。文件的指针将会放在文件的开头,这是默认模式。如果文件不存在,抛出异常 |
w | 以只写方式打开文件。如果文件存在会被覆盖。如果文件不存在,创建新文件 |
a | 以追加方式打开文件。如果该文件已存在,文件指针将会放在文件的结尾。如果文件不存在,创建新文件进行写入 |
r+ | 以读写方式打开文件。文件的指针将会放在文件的开头。如果文件不存在,抛出异常 |
w+ | 以读写方式打开文件。如果文件存在会被覆盖。如果文件不存在,创建新文件 |
a+ | 以读写方式打开文件。如果该文件已存在,文件指针将会放在文件的结尾。如果文件不存在,创建新文件进行写入 |
频繁的移动文件指针,会影响文件的读写效率,开发中更多的时候会以 只读、只写 的方式来操作文件
file = open("README", "a") file.write("123456") file.close()
5、按行读取文件内容
readline方法可以一次读取一行内容,方法执行后会把文件指针移到下一行,准备再次读取;
读取大文件的正确姿势:
file = open("README") while True: txt = file.readline() # 判断是否读取到内容 if not txt: break print(txt) file.close()
6、复制文件案例
小文件复制:打开一个已有文件,读取完整内容,并写入到另一个文件
file = open("README") new_file = open("NEWFILE", "w") txt = file.read() new_file.write(txt) file.close() new_file.close()
大文件复制:打开一个已有文件,逐行读取内容,并顺序写入到另外一个文件
file = open("README") new = open("NEWFILE", "a") while True: txt = file.readline() if not txt: break new.write(txt) file.close() new.close()
7、文件目录的常用管理操作
需要导入os模块
文件操作:
序号 | 方法名 | 说明 | 示例 |
---|---|---|---|
01 | rename | 重命名文件 | os.rename(源文件名, 目标文件名) |
02 | remove | 删除文件 | os.remove(文件名) |
目录操作:
序号 | 方法名 | 说明 | 示例 |
---|---|---|---|
01 | listdir | 目录列表 | os.listdir(目录名) |
02 | mkdir | 创建目录 | os.mkdir(目录名) |
03 | rmdir | 删除目录 | os.rmdir(目录名) |
04 | getcwd | 获取当前目录 | os.getcwd() |
05 | chdir | 修改工作目录 | os.chdir(目标目录) |
06 | path.isdir | 判断是否是文件 | os.path.isdir(文件路径) |
提示:文件或者目录操作都支持相对路径 和 绝对路径
8、文本文件的编码格式
ASCII编码:256个字符,一个字符占用一个字节
UTF-8编码:是UNICODE编码的一种编码格式,1-6个字节来表示一个字符,涵盖了地球上几乎所有地区的文字,大多数汉字会使用3个字节表示
Python 2.x 默认使用 ASCII
编码格式
Python 3.x 默认使用 UTF-8
编码格式
在 Python 2.x 文件的 第一行 增加以下代码,解释器会以 utf-8
编码来处理 python 文件
# *-* coding:utf8 *-*
# *-* coding:utf8 *-* hello = u"hello 世界" print(hello) """在Python 2.x中,即使指定了文件使用UTF-8的编码格式, 但是在遍历字符串时,仍然会以字节为单位遍历字符串 要能够正确的遍历字符串,在定义字符串时,需要在字符串的引号前, 增加一个小写字母u,告诉解释器这是一个unicode字符串(使用UTF-8编码格式的字符串)""" for c in hello: print(c)
9、eval函数
eval()函数十分强大:将字符串当成有效的表达式来求值并返回计算结果
# 基本的数学计算 In [1]: eval("1 + 1") Out[1]: 2 # 字符串重复 In [2]: eval("'*' * 10") Out[2]: '**********' # 将字符串转换成列表 In [3]: type(eval("[1, 2, 3, 4, 5]")) Out[3]: list # 将字符串转换成字典 In [4]: type(eval("{'name': 'xiaoming', 'age': 18}")) Out[4]: dict
计算器:
str = input("请输入计算题:") result = eval(str) print(result)
在开发时千万不要直接使用eval转换input的结果:
比如在以上代码的运行结果中输入:
请输入计算题:__import__('os').system('ls')
等价于:
import os
os.system("终端命令")