Python基础学习-----异常模块包序列化StringIO

异常

当使用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
有没有异常都会执行这个语句

自定义异常类

当我们代码有错误时,通常系统会报错,并弹出异常信息,其实我们也可以通过自定义异常来对一些报错进行处理:

  1. 自定义一个异常类CustomException
  2. __str__表示抛出异常显示的异常描述信息
  3. 通过raise关键字抛出自定义异常,raise还能抛出系统定义的异常
  4. 注意: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需要注意的地方
  1. 不要使用与系统文件相同的名字来创建模块,例如random。
  2. 主模块中不要有与导入模块相同的功能代码的名字,例如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)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值