异常
当使用python解释器去执行代码的时候,遇到了错误,在控制台输出错误信息,这个错误信息就是异常。代码遇到异常会终止执行。
- 提示:多数异常类都是继承Exception
- 可能出现异常的代码放到try语句里面
- 捕获到的异常会在except里面进行处理
'我输入字母,就不是加法了,所以我增加一个捕捉异常'
try:
num1 = input("输入第一个数字:")
num2 = input("输入第二个数字:")
result = int(num1)+int(num2)
print(result)
except Exception as e: #e表示异常对象
print(e,'\n','type of e is:',type(e))
print('请输入正确的数字')
输出:
输入第一个数字:1
输入第二个数字:a
invalid literal for int() with base 10: 'a'
type of e is: <class 'ValueError'>
请输入正确的数字
当一堆多个异常存在于try里面,只会识别出第一个异常,然后代码就会终止执行,即使后面也有异常。不过可以通过写多几个except来解决这个问题。如果没有异常就执行else,finally就是无论怎样都会执行(有无异常都执行)
try:
num1 = input("输入第一个数字:")
num2 = input("输入第二个数字:")
result = int(num1)+int(num2)
print(result)
except Exception as e: #e表示异常对象
print(e,'\n','type of e is:',type(e))
print('请输入正确的数字')
else:
print("没有异常执行else")
finally:
print("有没有异常都会执行这个语句")
输出:
输入第一个数字:1
输入第二个数字:2
3
没有异常执行else
有没有异常都会执行这个语句
自定义异常类
当我们代码有错误时,通常系统会报错,并弹出异常信息,其实我们也可以通过自定义异常来对一些报错进行处理:
- 自定义一个异常类CustomException
- __str__表示抛出异常显示的异常描述信息
- 通过raise关键字抛出自定义异常,raise还能抛出系统定义的异常
- 注意:raise只能抛出异常类型
class CustomException(Exception):
def __init__(self,content):
self.content = content
#__str__表示抛出异常显示的异常描述信息
def __str__(self):
return "我是自定义异常,因为数据不是a,异常数据为%s" % self.content
#抛出自定义异常,
content = input("请输入数据:")
if content != 'a':
#抛出自定义异常
raise CustomException(content)
# 也可以抛出系统定义的类
raise NameError("name is not defined")
输出:
请输入数据:1
Traceback (most recent call last):
raise CustomException(content)
__main__.CustomException: 我是自定义异常,因为数据不是a,异常数据为1
模块
通俗点讲,一个py文件就是一个模块,模块是用于管理功能代码
模块的作用:可以定义类,定义函数,定义全局变量,执行对应的功能代码操作
内置模块
python内部有许多可用的模块,例如:time,random
import time
import random
time.sleep(3)
print("hhh") #3秒后才打印hhh
result = random.randint(1,5)#随机产生一个1-5之间的整数
print(result)
输出:
3秒以后输出
hhh
1
自定义模块
- 模块的命名规则与变量名的命名规则一样,统一使用下划线命名法
- 可以由字母,数字,下划线组成, 不能用数字作为开头
定义一个自定义模块first_module.py:
#定义全局变量
g_num = 10
#定义函数
def show():
print("函数")
#定义类
class Person(object):
def __init__(self,name):
self.name = name
def show_msg(self):
print(self.name)
在主模块中调用first_module:
import first_module
#使用模块中的功能代码
print(first_module.g_num) #使用变量
first_module.show() #使用函数
man = first_module.Person("Tony") #使用类创建对象
man.show_msg()
输出:
10
函数
Tony
判断主模块:
因为每个文件都是py文件,而我们要判断一下哪个文件是main文件,主模块就是你要执行的那个模块,使用print(__name__)
,可以查看模块名字。
使用if __name__ == "__main__":
判断是否为主模块,如果是被调用的模块,那么这个语句下的代码不会执行的。
second_module.py:
g_score = 100
def show_msg():
print("show msg")
def sum_num(num1,num2):
result = num1+num2
return result
#主模块:执行的那个模块,就是主模块
#查看模块名
print(__name__)
if __name__ == "__main__": #判断是不是主模块
#测试sum_num函数是否有问题
result = sum_num(1,3)
print(result)
main.py:
import second_module
r = second_module.sum_num(3,2)
print(r)
输出:
second_module #这个就是在second module中打印出来的,因为没有放到判断里面
5
模块的导入方法:
- import导入
import first_module
man = first_module.Person("Tony") #使用类创建对象
man.show_msg()
- From导入
from first_module import Person
from first_module import show
per = Person("Tony")
print(per.name)
show()
或者直接使用*,导入全部功能代码
from first_module import *
使用__all__来限定可以使用的功能代码:(只会限制from xx import *)
当限制了功能后,主模块不能使用没有被允许使用的功能,若使用会报错
在first_module中写下这一行代码:
__all__=["g_num"] '限制主模块只能用g_num,到使用*号导入'
在main文件中:
from first_module import *
print(g_num)
show()
输出:
10
Traceback (most recent call last):
show()
NameError: name 'show' is not defined
import给模块设置别名
import first_module as first
print(first.g_num)
10
import需要注意的地方
- 不要使用与系统文件相同的名字来创建模块,例如random。
- 主模块中不要有与导入模块相同的功能代码的名字,例如show()函数,如果要使用导入模块的函数,只能使用
first_module.show()
包
包可以理解为一个文件夹,只不过文件夹里面有一个__init__.py文件,包是用于管理模块的,模块是管理功能的。
在pycharm中很简单,直接创建Python Package, 会自动生成__init__.py文件,我添加了first和second模块,并调用一下它们。
first.py:
def show():
print("第一模块")
second.py:
def show():
print("第二模块")
main.py:
from first_package import first
from first_package import second
first.show()
second.show()
输出:
第一模块
第二模块
当使用from 包名 import *
时,默认不会导入包里面的所有模块,需要在init文件中使用__all__去指定导入模块
__init__.py:
__all__ = ["first","second"]
main.py:
from first_package import *
first.show()
second.show()
输出:
第一模块
第二模块
直接导入包Import first_package
是不会导入对应模块,需要在init文件中自己导入
init文件:
from first_package import first
main文件:
import first_package
first_package.first.show()
first_package.second.show()
输出:
第一模块
AttributeError: module 'first_package' has no attribute 'second'
这种写法也是可以的 from . import *
,从当前包导入所有模块
String IO
把字符串数据直接写入到内存中
- StringIO的操作与文件读写的操作很类似
import io
str_io = io.StringIO()
#往内存写入字符串数据
str_io.write("helloworld")
'获取数据第一种方式'
# content = str_io.getvalue()
# print(content)
'获取数据第二种方式,光标会移动到末尾再读取,所以要设置指针'
'设置文件指针位置到文件开头'
str_io.seek(0)
'默认全部读取出来,read(2)表示读取指定长度'
result = str_io.read(2)
print(result)
输出:
he
BytesIO
from io import BytesIO
byte_io = BytesIO()
byte_io.write("哈哈".encode("utf-8"))
result = byte_io.getvalue()
print(result)
content = result.decode("utf-8")
print(content)
输出:
b'\xe5\x93\x88\xe5\x93\x88'
哈哈
序列化
把内存中的数据保存到本地,可以做到持久化存储
- pickle 比较通用,可以序列化任意对象类型 【JSON也可以】
- pickle.dump()这句话会得到二进制数据,而写入文件是要str数据,文件访问模式使用wb才可以
- json恰好相反,得到的是str数据,需要encoding=”utf-8"
- json的不能序列化的类型:自定义类型
序列化:
import pickle
file = open("my_list.serialize","wb")
my_list = [{"name":"Tony","age":20},{"name":"Ben","age":22}]
pickle.dump(my_list,file) #把数据序列化到文件中
file.close()
反序列化:
file = open("my_list.serialize","rb")
ml = pickle.load(file)
print(ml)
file.close()
输出:
[{'name': 'Tony', 'age': 20}, {'name': 'Ben', 'age': 22}]
类的序列化与反序列化
class Student(object):
def __init__(self):
self.name = "Tony"
self.age = 20
stu = Student()
file = open("stu.serialize","wb")
#序列化自定义类型对象
pickle.dump(stu,file)
file.close
file = open("stu.serialize","rb")
stu = pickle.load(file)
print(stu.name,stu.age)
file.close()
输出:
Tony 20
这种用pickle比较好办,json其实也可以操作,不过json不能直接序列化自定义类对象,而是要序列化其属性的字典类型, json.dump(stu.__dict__,file)