Python基础课--第十六节 异常&⽂件 遇到 运行python文件报SyntaxError: (unicode error) ‘unicodeescape‘ codec can‘t decode

1 异常的简介

  • 程序在运⾏过程中可能会出现⼀些错误。⽐如: 没有赋值的变量,使⽤了不存在的索引,两个不同类型的数据相加…这些错误我们称之为异常
  • 处理异常 程序运⾏时出现异常,⽬的并不是让我们的程序直接终⽌!Python是希望在出现异常时,我们可以编写代码来对异常进⾏处理
  • 异常以后的代码都不会执行
    语法(try语句):
    try:
    代码块(可能会出现错误的语句)
    except 异常类型 as异常名:
    代码块(出现错误以后的处理方式)
    except 异常类型 as异常名:
    代码块(出现错误以后的处理方式)

    else:
    代码块(没有错误时要执行的语句)
    finally:
    代码块(是否有异常都会执行)
    try是必须的 else有没有都可以
    except和finally⾄少有⼀个
# try 语句
print('hello')
try:
    print(10/0)
except:
    print('出错了兄弟')
print('python')
结果
hello
出错了兄弟
python
# try 语句
print('hello')
try:
    print(10/2)
except:
    print('出错了兄弟')
else:
    print('程序正常执行,没有错误')
    
print('python')
结果
hello
5.0
程序正常执行,没有错误
python

2 异常的传播

  • 当在函数中出现异常时,如果在函数中对异常进行了处理,则异常不会再传播,如果函数中没有对异常进行处理,则异常会继续像函数调用处传播,
  • 如果函数调用处处理了异常,则不再传播,如果没有处理则继续向调用处传播,直到传递到全局作用域(主模块),如果依然没有处理,则程序终止,并且显示异常信息。
def fn():

    print('hello fn')
    print(10 / 0)

try:
    fn()

except:
    pass
 结果
 hello fn
def fn():

    print('hello fn')
    print(10 / 0)

def fn2():

    print('hello fn2')
    fn()

def fn3():

    print('hello fn3')
    fn2()

fn3()
结果
Traceback (most recent call last):
  File "D:/Users/RAZER/PycharmProjects/lect12-16/lect16/异常的传播.py", line 31, in <module>
    fn3()
hello fn3
  File "D:/Users/RAZER/PycharmProjects/lect12-16/lect16/异常的传播.py", line 29, in fn3
    fn2()
  File "D:/Users/RAZER/PycharmProjects/lect12-16/lect16/异常的传播.py", line 24, in fn2
hello fn2
    fn()
hello fn
  File "D:/Users/RAZER/PycharmProjects/lect12-16/lect16/异常的传播.py", line 19, in fn
    print(10 / 0)
ZeroDivisionError: division by zero
  • 当程序运行过程中出现异常以后,所有的异常信息会被专门保存到一个异常对象当中,而异常传播时,实际上就是异常对象抛给了调用处,NameError类(是个类)专门处理变量的错误

3 异常对象

  • except 后不跟任何内容,此时,他会捕获所有的异常
print('异常出现前')

try:
    print(a)
    print(10/0)
except:
    # except 后不跟任何内容,此时,他会捕获所有的异常
    print('处理异常的逻辑')

print('异常出现后')
结果
异常出现前
处理异常的逻辑
异常出现后
  • NameError只能捕获name异常
    开始时
print('异常出现前')

try:
    print(a)
    print(10/0)
except NameError:
    # except 后不跟任何内容,此时,他会捕获所有的异常
    # print('处理异常的逻辑')
    print('出现NameError异常了')

print('异常出现后')
结果
异常出现前
出现NameError异常了
异常出现后

注释掉 print(a)后

print('异常出现前')

try:
    # print(a)
    print(10/0)
except NameError:
    # except 后不跟任何内容,此时,他会捕获所有的异常
    # print('处理异常的逻辑')
    print('出现NameError异常了')

print('异常出现后')
结果
异常出现前
Traceback (most recent call last):
  File "D:/Users/RAZER/PycharmProjects/lect12-16/lect16/异常对象.py", line 5, in <module>
    print(10/0)
ZeroDivisionError: division by zero

然后添加 except ZeroDivisionError:

print('异常出现前')

try:
    # print(a)
    print(10/0)
except NameError:
    # except 后不跟任何内容,此时,他会捕获所有的异常
    # print('处理异常的逻辑')
    print('出现NameError异常了')
except ZeroDivisionError:
    # except 后不跟任何内容,此时,他会捕获所有的异常
    # print('处理异常的逻辑')
    print('出现ZeroDivisionError异常了')

print('异常出现后')
结果
异常出现前
出现ZeroDivisionError异常了
异常出现后
  • Exception是所有异常类的父类

  • 如果except后面不跟任何内容,则此时会捕获到所有的异常,如果except后面跟着一个异常类型,那么此时它只会捕获该类型的异常。

  • Exception是所以异常类的父类,所以如果except后跟的是Exception,它会捕获到所有的异常,赋值给变量只会穿第一个异常。
    要想知道是什么类型的错误

print('异常出现前')

lst = []

try:
    # print(a)
    lst + 'hello'  # 除以0在下面,所以先补货上面的
    print(10/0)
# except NameError:
#     # except 后不跟任何内容,此时,他会捕获所有的异常
#     # print('处理异常的逻辑')
#     print('出现NameError异常了')
# except ZeroDivisionError:
#     # except 后不跟任何内容,此时,他会捕获所有的异常
#     # print('处理异常的逻辑')
#     print('出现ZeroDivisionError异常了')
except Exception as e:
    # Exception是所有异常类的父类
    print('出异常了',e,type(e))

print('异常出现后')
结果
异常出现前
出异常了 can only concatenate list (not "str") to list
异常出现后

上述代码不是最终版本,还可以加上finally

print('异常出现前')

lst = []

try:
    # print(a)
    # lst + 'hello'
    print(10/2)
# except NameError:
#     # except 后不跟任何内容,此时,他会捕获所有的异常
#     # print('处理异常的逻辑')
#     print('出现NameError异常了')
# except ZeroDivisionError:
#     # except 后不跟任何内容,此时,他会捕获所有的异常
#     # print('处理异常的逻辑')
#     print('出现ZeroDivisionError异常了')
except Exception as e:
    # Exception是所有异常类的父类
    print('出异常了',e,type(e))

finally:
    print('无论是否出现异常,该语句都会执行')

print('异常出现后')
结果
异常出现前
5.0
无论是否出现异常,该语句都会执行
异常出现后

语法(try语句):
try:
代码块(可能会出现错误的语句)
except 异常类型 as异常名:
代码块(出现错误以后的处理方式)
except 异常类型 as异常名:
代码块(出现错误以后的处理方式)
可以print(异常名,type(异常名))

else:
代码块(没有错误时要执行的语句)
finally:
代码块(是否有异常都会执行)
try是必须的 else有没有都可以
except和finally⾄少有⼀个

4. 自定义异常对象

  • 抛出异常,可以是用raise语句来抛出异常,raise语句后面需要跟一个异常类或者是异常的实例,抛出异常的目的,告诉调用者这里调用时可能出现问题,希望你自己处理下。

  • 定义异常类,只需要继承Exception就可以了

# 自定义异常对象
class MyError(Exception):
    pass


def add(a, b):
    # 如果a b中有负数,就像调用处抛一个异常
    if a < 0 or b < 0:
        raise MyError('自定义异常信息,参数中不能有负数')
    r = a + b
    return r


print(add(-1, 2))
结果
Traceback (most recent call last):
  File "D:/Users/RAZER/PycharmProjects/lect12-16/lect16/异常对象.py", line 40, in <module>
    print(add(-1, 2))
  File "D:/Users/RAZER/PycharmProjects/lect12-16/lect16/异常对象.py", line 35, in add
    raise MyError('自定义异常信息,参数中不能有负数')
__main__.MyError: 自定义异常信息,参数中不能有负数

5 文件打开

  • 通过Python来对计算机中的各种文件进行增删改查的操作。
    I/O(Input/Output)

  • 操作文件的步骤:

    打开文件
    对文件进行各种操作(读、写)
    关闭

  • open(file, mode=‘r’, buffering=None, encoding=None, errors=None, newline=None, closefd=True)
    使用open()函数来打开一个文件

  • 参数:
    file是要打开文件的名字(路径),如果目标文件和当前文件在同一级目录下,则直接使用文件名即可打开。

  • 遇到报错 运行python文件报SyntaxError: (unicode error) ‘unicodeescape’ codec can’t decode bytes in position 2-3: tr
    解决办法

https://blog.csdn.net/xd060606/article/details/87164798

  • 返回值:
    返回的是一个对象,这个对象就是代表了当前打开的文件。

6 读取并关闭文件

  • 读取文件
    read()方法来读取文件的内容,它会将内容全部保存到一个字符串返回
file_name = 'demo.txt'

file_obj = open(file_name)

# read()函数 读取文件内容,将内容全部保存到一个字符串返回

content = file_obj.read()

print(content)
结果
my world

发现当txt文件里是中文的时候,打印出错。

  • 关闭文件
    close()方法用来关闭文件
file_name = 'demo.txt'

file_obj = open(file_name)

# read()函数 读取文件内容,将内容全部保存到一个字符串返回

content = file_obj.read()

print(content)

# 关闭文件 调用close()
file_obj.close()

file_obj.read()  # ValueError: I/O operation on closed file.
结果
my world
Traceback (most recent call last):
  File "D:/Users/RAZER/PycharmProjects/lect12-16/lect16/关闭文件.py", line 15, in <module>
    file_obj.read()
ValueError: I/O operation on closed file.
  • with … as语句
    在with语句中可以直接使用file_obj来操作文件,此时这个文件只能在with中使用,一旦with结束文件则会自动close()关闭。
# with … as语句

file_name = 'demo.txt'

with open(file_name) as file_obj:

    print(file_obj.read())

print(file_obj.read())
结果
Traceback (most recent call last):
  File "D:/Users/RAZER/PycharmProjects/lect12-16/lect16/关闭文件.py", line 25, in <module>
my world
    print(file_obj.read())
ValueError: I/O operation on closed file.
  • 寻找异常
file_name = 'hello'

try:
    with open(file_name) as file_obj:

        print(file_obj.read())
except FileNotFoundError:
    print(f'{file_name}文件不存在')
 结果
 hello文件不存在

7 读取较大文件

  • 通过read()函数来读取文件的内容。
  • 调用open()来打开一个文件,可以将文件分成两种类型:
    ·一种是纯文本文件(使用utf-8等编码写的文本文件)
    ·一种是二进制文件(图片、音频、PPT等文件)
  • open()这个函数打开文件时,默认是以文本文件的形式打开的,处理文本文件时,有时候需要制定文件的编码。
file_name = 'demo2.txt'

try:
    with open(file_name,encoding='utf-8') as file_obj:

        content = file_obj.read()

        print(content)

except FileNotFoundError:
    print(f'{file_name}文件不存在')
结果
文件内容
  • 如果直接调用read()这个函数,它会将文本内容全部读取,如果要读取的内容文件比较大的情况,会一次性将文件的内容加载到内存中,容易导致内存泄漏。
  • read()函数可以接收一个size作为参数,该参数用来指定读取的字符的数量,默认值是-1,它会读取文件中所有的字符。
  • 可以为size指定一个值,这样read()函数会读取指定数量的字符,每一次读取都是从上次读取到的位置开始读取,如果字符的数量小于size,则会读取剩余所有的字符。
file_name = 'demo.txt'

try:
    with open(file_name,encoding='utf-8') as file_obj:

        # 定义一个变量 来保存结果
        file_content = ''

        # 定义一个变量 指定每次读取的大小
        chunk = 100
        # 创建一个循环来读取内容
        while True:

            content = file_obj.read(chunk)

            # 检查是否读完文件
            if not content:
                # 内容读取完毕 退出循环
                break
            # print(content,end='')  # 如果一行内容过长,会自动换行,此时可加一个 end=''
            file_content += content

except FileNotFoundError:
    print(f'{file_name}文件不存在')
print(file_content,end='')  # 如果一行内容过长,会自动换行,此时可加一个 end=''
结果
文件内容

8 其他的读取方式

  • readline()可以用来读取一行内容

file_name = 'demo2.txt'

with open(file_name,encoding='utf-8') as file_obj:

    # print(file_obj.read())
    print(file_obj.readline())
    print(file_obj.readline())
结果
两行文件的内容
  • readlines()该方法也是用于一行一行的读取内容,它会将读取到的内容封装到列表中返回
  • readlines()会一次性读取文件内容以列表形式返回

file_name = 'demo2.txt'

with open(file_name,encoding='utf-8') as file_obj:

    # print(file_obj.read())
    # r = file_obj.readline()
    # print(r)

    R = file_obj.readlines()
    print(R)
    print(R[0])
结果
['我的世界,因为你而变得甜蜜。\n', '手提花篮,把相思卖\n', '大街过去,小巷出来\n', '叫了一声,相思卖']
我的世界,因为你而变得甜蜜。

9 文件的写入

  • open()中有一个mode参数,默认为’r’,表示只能读取文件,而读取文件是不能向文件中去写入的,使用open()函数打开文件时需要制定打开文件所要的操作(读、写、追加),如果不指定操作类型,默认是以读取文件。
file_name = 'demo2.txt'

with open(file_name,encoding='utf-8') as file_obj:

    file_obj.write('nice to meet you')  # io.UnsupportedOperation: not writable
  • write():向文件中写入内容,如果要操作的是一个文本文件的时候,需要我们传递一个字符串作为参数
  • r:表示只读。
file_name = 'demo3.txt'

with open(file_name,'w',encoding='utf-8') as file_obj:

    r = file_obj.write(str(123)+'\n')
    print(r)
  结果
  4

w:表示可以写 所以我们可以使用w来写入文件,如果文件不存在会创建文件,如果文件存在则会覆盖原文件的内容。

file_name = 'demo3.txt'

with open(file_name,'w',encoding='utf-8') as file_obj:

    # write()来向文件中写入内容
    # 如果要操作的是一个文本文件的时候,需要我们传递一个字符串作为参数

    # file_obj.write('nice to meet you')  # io.UnsupportedOperation: not writable
    file_obj.write('abc\n')
    file_obj.write('def')
    file_obj.write('wxy')
    file_obj.write(str(123))
结果
abc
defwxy123

a:表示追加内容 如果文件不存在会创建文件,如果文件存在则会像文件中追加内容。

file_name = 'demo.txt'

with open(file_name,'a',encoding='utf-8') as file_obj:

    # write()来向文件中写入内容
    # 如果要操作的是一个文本文件的时候,需要我们传递一个字符串作为参数
    # r表示只读
    # w表示可以写

    # file_obj.write('nice to meet you')  # io.UnsupportedOperation: not writable
    file_obj.write('abc\n')
    file_obj.write('def')
    file_obj.write('wxy\n')
    file_obj.write('Nan Li\n')
    r = file_obj.write(str(123)+'\n')   # 有返回值,几个字符值
    print(r) # 4
结果
demo里面多了
nice to meet you
abc
defwxy
Nan Li
123

+:表示操作符增加功能。
r+:表示既可读又可写,文件不会报错。
x:表示创建文件,如果文件不存在就创建,如果存在就报错。
文件存在报错:FileExistsError: [Errno 17] File exists: ‘demo.txt’
文件不存在:就创建

10 二进制文件

读取模式:
‘t’:读取文本文件(默认值)
‘b’:读取二进制文件

读取文本文件时,size是以字符为单位
读取二进制文件时,size是以字节为单位

  • 只读200k的歌曲

file_name = r'D:\Users\RAZER\PycharmProjects\lect12-16\lect16\1.mp3'
# 读取模式
# t 读取文本文件(默认值)
# b 读取二进制文件
with open(file_name,'rb') as file_obj:  # 只读时默认是r,可省略,但是有其他时,r不能省略

    # print(file_obj.read(100))  # UnicodeDecodeError: 'gbk' codec can't decode byte 0xff in position 21: illegal multibyte sequence

    # 将读取到的内容写出来
    # 定义一个新的文件
    new_name = 'abc.mp3'

    with open(new_name,'wb') as new_obj:

        # 定义读取的大小
        chuck = 1024 * 200

    # while True:

        # 读取数据
        content = file_obj.read(chuck)

        # # 判断是否读取完毕
        # if not content:
        #     break

        # 将内容写到新的文件当中
        new_obj.write(content)
  • 读取全部歌曲,用循环

file_name = r'D:\Users\RAZER\PycharmProjects\lect12-16\lect16\1.mp3'
# 读取模式
# t 读取文本文件(默认值)
# b 读取二进制文件
with open(file_name,'rb') as file_obj:  # 只读时默认是r,可省略,但是有其他时,r不能省略

    # print(file_obj.read(100))  # UnicodeDecodeError: 'gbk' codec can't decode byte 0xff in position 21: illegal multibyte sequence

    # 将读取到的内容写出来
    # 定义一个新的文件
    new_name = 'abc.mp3'

    with open(new_name,'wb') as new_obj:

        # 定义读取的大小
        chuck = 1024 * 100

        while True:

            # 读取数据
            content = file_obj.read(chuck)

            # 判断是否读取完毕
            if not content:
                break

            # 将内容写到新的文件当中
            new_obj.write(content)

11 读取文件的位置

tell():用来检查当前读取的位置
seek():可以修改当前读取的位置
参数:
0:从头开始(默认)
1:从当前位置
2:从最后位置计算

12 文件的其他操作

os库

listdir() 获取当前目录结构

import os

print(os.listdir())
结果
['1.mp3', 'abc.mp3', 'demo.txt', 'demo2.txt', 'demo3.txt', 'demo4.txt', '__init__.py', '关闭文件.py', '其他的读取方式.py', '异常对象.py', '异常的传播.py', '异常的简介.py', '操作二进制文件.py', '文件打开.py', '文件的写入.py', '读取文件.py', '较大文件的读取.py']

os.chdir(‘c:/’) 切换盘符
os.getcwd() 获取当前所在的目录

import os

r = os.getcwd()
print(r)

os.mkdir(‘abc’) 在当前目录创建
os.rmdir(‘abc’)删除目录

你可能感兴趣的:(python)