Python常见错误提示与异常处理

错误可以分为两种:
一个是代码运行前的语法错误;
另外一个是逻辑错误。
异常指的就是非正常状态,在python里面,一般都是用异常对象来表示异常。若程序在编译或运行过程中发生错误,程序的执行过程就会发生改变,抛出异常对象,程序流进入异常处理。

本人所遇错误提示记录

AttributeError: module ‘tkinter’ has no attribute ‘messagebox’

解决: from tkinter import messagebox
注意:from import *是不行的。

常见错误与异常收集

在运行或编写一个程序时常会遇到错误异常,这时python会给你一个错误提示类名,告诉出现了什么样的问题(Python是面向对象语言,所以程序抛出的异常也是类)。能很好的理解这些错误提示类名所代表的意思,可以帮助你在最快的时间内找到问题所在,从而解决程序上的问题是非常有帮助的。

搜集了一些python最重要的内建异常类名,并做了简单的介绍:

AttributeError:属性错误,特性引用和赋值失败时会引发属性错误

NameError:试图访问的变量名不存在

SyntaxError:语法错误,代码形式错误

Exception:所有异常的基类,因为所有python异常类都是基类Exception的其中一员,异常都是从基类Exception继承的,并且都在exceptions模块中定义。

IOError:一般常见于打开不存在文件时会引发IOError错误,也可以解理为输出输入错误

KeyError:使用了映射中不存在的关键字(键)时引发的关键字错误

IndexError:索引错误,使用的索引不存在,常索引超出序列范围,什么是索引

TypeError:类型错误,内建操作或是函数应于在了错误类型的对象时会引发类型错误

ZeroDivisonError:除数为0,在用除法操作时,第二个参数为0时引发了该错误

ValueError:值错误,传给对象的参数类型不正确,像是给int()函数传入了字符串数据类型的参数。

1)忘记在if,elifelse,for,while,class ,def声明末尾添加:(导致 “SyntaxError :invalid syntax”)

该错误将发生在类似如下代码中:

if spam == 42

    print(‘Hello!’)

2)使用=而不是==(导致“SyntaxError:invalidsyntax”)

=是赋值操作符而==是等于比较操作。该错误发生在如下代码中:

if spam = 42:

    print(‘Hello!’)

3)错误的使用缩进量。(导致“IndentationError:unexpected indent”、“IndentationError:unindent does not match any outer indetation level”以及“IndentationError:expected an indented block”)

记住缩进增加只用在以:结束的语句之后,而之后必须恢复到之前的缩进格式。该错误发生在如下代码中:

print(‘Hello!’)

print(‘Howdy!’)

或者:

if spam == 42:

print(‘Hello!’)

 print(‘Howdy!’)

或者:

if spam == 42:

print(‘Hello!’)

4)尝试修改string的值(导致“TypeError:’str’objectdoesnotsupportitemassignment”)

string是一种不可变的数据类型,该错误发生在如下代码中:

spam = ‘I have apet cat.’

spam[13] = ‘r’

print(spam)

而你实际想要这样做:

spam = ‘I have apet cat.’

spam = spam[:13] +’r’ + spam[14:]

print(spam)

5)在字符串首尾忘记加引号(导致“SyntaxError:EOLwhilescanningstringliteral”)

该错误发生在如下代码中:

print(Hello!’)

或者:

print(‘Hello!)

或者:

myName = ‘Al’

print(‘My name is ‘+ myName + . How are you?’)

6)变量或者函数名拼写错误(导致“NameError:name’fooba’isnotdefined”)

该错误发生在如下代码中:

foobar = ‘Al’

print(‘My name is ‘+ fooba)

或者:

spam = ruond(4.2)

或者:

spam = Round(4.2)

7)尝试使用Python关键字作为变量名(导致“SyntaxError:invalid syntax”)

Python关键不能用作变量名,该错误发生在如下代码中:

class = ‘algebra’

Python3的关键字有:and, as, assert, break, class, continue, def, del, elif,else, except, False, finally, for, from, global, if, import, in, is, lambda,None, nonlocal, not, or, pass, raise, return, True, try, while, with, yield


错误与异常处理

1.错误可以分为两种:
一个是代码运行前的语法错误;另外一个是逻辑错误
        a)语法错误(这种错误,根本过不了python解释器的语法检测,必须在程序执行前就改正)
          def test:
                   xxx
              SyntaxError: invalid syntax
                  其他语法的错误
       b)逻辑错误
                用户输入不完整(比如输入为空)或者输入非法(输入不是数字)
                 i=input(“xxx: “)
                 int(i)
                 print( )

         执行结果是:ValueError: invalid literal for int() with base 10: ‘fsf’

2.异常
(1)异常指的就是非正常状态,在python里面,一般都是用异常对象来表示异常。若程序在编译或运行过程中发生错误,程序的执行过程就会发生改变,抛出异常对象,程序流进入异常处理。如果异常对象没有被处理或捕捉,程序就会执行回溯(Traceback)来终止程序。

   异常的分类:
        a)程序遇到逻辑或算法错误
         b)运行过程中计算机错误:内存不够或者io错误
   异常的步骤:
       a)异常产生,检查到了错误,解释器也认为是不正常的,就会抛出异常
         b)异常处理,截取到异常,系统可能忽略,要么终止程序来处理异常

(2)异常处理

            a)try语句:
            第一步,先执行try语句(处在两个关键字try 、except中间的),没有异常发生的话,就不执行except后面的语句;try语句执行后直接结束。
 一旦在执行try语句时发生了异常,那么try语句中的代码将会忽略。如果异常的类型和 except 之后的名称相匹配,那么对应的except语句将被执行。最后再去执行 try 语句之后的代码。

           b)一个 try 语句可能包含多个except语句,分别来处理不同的特定的异常。最多只有一个分支会被执行!处理程序将只针对对应的try中的异常进行处理,
一个except子句可以同时处理多个异常,这些异常将被放在一个括号里成为一个元组,例如:

except (RuntimeError, TypeError, NameError):
         pass

try except 语句还有一个可选的else子句,如果使用这个子句,那么必须放在所有的except子句之后。这个子句将在try语句没有发生任何的异常的时候才会去执行   例如:

def doage():
    age=int(input("请输入年龄:  "))
    if 1<= age <=100:
        print("正常")
    else:
        raise ageException("年龄只能在1至100之间")
try:
    doage()
except ageException as ii:
    print(ii)
else:
    print("您是否输入错误?")

执行结果:只要我输入的数字在1~100范围内,else语句就会跟着执行;反之就不出现

使用 else 子句比把所有的语句都放在 try 子句里面要好,这样可以避免一些意想不到的、而except又没有捕获的异常。

3.常见的异常

AttributeError                          试图访问一个对象没有的属性,比如foo.x,但是foo没有属性x
IOError                                      输入/输出异常;基本上是无法打开文件
ImportError                              无法引入模块或包;   基本上是路径问题或名称错误
IndentationError                       语法错误(的子类) ;代码没有正确对齐
IndexError                                下标索引超出序列边界,比如当x只有三个元素,却试图访问x[5]
KeyError                                    试图访问字典里不存在的键
KeyboardInterrupt Ctrl+C         被按下
NameError                              尝试访问一个没有申明的变量
SyntaxError Python              代码非法,代码不能编译(个人认为这是语法错误,写错了)
TypeError                               传入对象类型与要求的不符合
UnboundLocalError             试图访问一个还未被设置的局部变量,基本上是由于另有一个同名的全局变量,导致你                                                以为正在访问它
ValueError                           传入一个调用者不期望的值,即使值的类型是正确的

万能异常(所有异常都包含,不具体到某一步)

在python的异常中,有一个万能异常:Exception,可以捕获任意异常

class ageException(Exception):
    pass

raise主动触发异常

class hexinException(BaseException):
    def __init__(self,msg):
        self.msg=msg
    def __str__(self):
        return self.msg
 
try:
    raise hexinException('类型错误')
except hexinException as e:
    print(e)

课堂练习:


#定义一个方法:在此方法内不进行异常处理
#定义一个列表list1,通过下标访问最后一个元素,list1[1list1.length]
#定义一个调用的方法:捕获异常
 
def method():
    list1 = [0, 1, 2, 3, 4, 5]
    list1[len(list1)]
def methoderror():
    try:
        method()
    except IndexError as ie:
        print("下标超出范围")
        print(ie)
methoderror()
#年龄的自定义异常,在1-100岁之间为正常,否则抛出异常
class ageException(Exception):
    pass
def doage():
    age=int(input("请输入年龄:  "))
    if 1<= age <=100:
        print("正常")
    else:
        raise ageException("年龄只能在1至100之间")
try:
    doage()
except ageException as ii:
    print(ii)

关于错误和异常

(1)概念:错误是无法通过其他代码进行处理问题,如语法错误和逻辑错误,语法错误是单词或格式等写错,只能根据系统提示去修改相应的代码,逻辑错误是代码实现功能的逻辑有问题,系统不会报错,也是只能找到相应的代码进行修改;异常是程序执行过程中,出现的未知问题,这里语法和逻辑都是正确的,可以通过其他代码进行处理修复,如可以通过if判定语句来避免对年龄进行赋值时输入了字符而出现异常的情况,如使用捕捉异常可以避免除零异常等

(2)关于常见的系统异常:

除零异常(ZeroDiviceError):被除数写成了0

名称异常(NameError):变量未定义

类型异常(TypeError):不同类型数据进行相加

索引异常(IndexError):超出索引范围

键异常(KeyError):没有对应名称的键

值异常(ValueError):将字符型数据转换成整型数据

属性异常(AttributeError):对象没有对应名称的属性

迭代器异常(StopIteration):迭代次数超出迭代器内容个数

(3)关于python异常的继承关系树图

(4)异常的解决思路

系统内置了很多应用场景,我们在运行程序过程中,一旦触发相关场景,系统就会向外抛出相应的问题,这就是系统抛出的异常

预防:添加容错处理,代码虽会触发异常,但使用容错处理可以不让异常被触发

解决:如果容错代码过多时,会使得整个程序非常混乱,这时可以使用捕捉异常进行处理

解决方案1–捕捉异常的完整机构如下:

注意1:

try:
1 / 0
print(name)
except ZeroDivisionError as z:
print(“除零错误”)
except NameError as n:
print(“名字错误”)
else:
print(“代码没错”)
finally:
print(“后续代码执行”)
这里当1 / 0 执行时,出现异常,会跳过print(name)去执行except ZeroDivisionError as z:进行捕捉,从而不会去执行print(name),故后面对其的捕捉也是无效的

注意2:

try:
# 1 / 0
print(name)
except (ZeroDivisionError, NameError) as z:
print(“异常”)
else:
print(“代码没错”)
finally:
print(“后续代码执行”)
这里如果对多个异常的处理是相同的,则可以将这些异常进行合并处理

注意3:

try:
# 1 / 0
print(name)
except Exception as z:
print(“异常”)
else:
print(“代码没错”)
finally:
print(“后续代码执行”)
如果不知道具体是什么异常,可以直接使用Exception进行捕捉,因为这些常见的异常都是继承自Exception的

解决方案2–with语句

实现步骤:

1.上下文表达式context_expression要返回一个上下文管理器

  1. 执行上下文管理器的enter()方法,如果写了as target,则把enter()方法的返回值赋值给target

3.执行body语句体

4.执行上下文管理器对象的exit()方法

注意:上下文表达式context_expression必须要返回一个上下文管理器,上下文管理器是实现了上下文管理协议的对象,而上下文管理协议中必须包含enter()方法和exit()方法。例子:

with open(“a.txt”, “r”) as f:
f.readlines()
这里先由open(“a.txt”, “r”)生成上下文管理器,而该上下文管理器的enter()方法就是打开文件,再将文件句柄赋值给f,执行完f.readlines(),会自动执行上下文管理器的exit()方法,这里即关闭文件。这种写法避免了在文件处理过程中出现异常时导致的后续close()方法无法执行的问题,同时也简化了代码,避免多个文件的打开和关闭代码重复问题

(5)自定义上下文管理器

方法一:利用类来创建上下文管理器。原因–上下文管理器是一个包含enter()方法和exit()方法的对象

import traceback
class Test:
def enter(self):
print(“enter”)
return “xxx”
def exit(self, exc_type, exc_val, exc_tb):
print(self, exc_type, exc_val, exc_tb)
print(traceback.extract_tb(exc_tb))
print(“exit”)
return True
with Test() as t:
print(“测试”, t)
1 / 0
其中enter()方法的返回值将会赋值给t,即xxx;执行with语句体后出现的异常会抛给exit()方法,其参数分别代表的时异常的类型,异常的值(内容)和异常的追踪信息,异常追踪信息可以使用traceback模块的extract_tb方法单独抽取出来;exit()方法的返回值决定异常的抛出与否,如果返回True,则异常在内部消化,不会抛出,程序正常运行,如过返回False,则对外抛出异常,程序终止

方法二:利用生成器函数来创建上下文管理器

import contextlib
@contextlib.contextmanager
def shengchengqi():
print(1)
yield 6
print(2)
with shengchengqi() as scq:
print(3, scq)
这里需要使用contextlib模块中的contextlib.contextmanager装饰器对生成器函数进行装饰,使得其编程一个上下文管理器,这里实现的是将print(1)当作enter()方法执行,将print(2)当作exit()方法执行,而yield后面的值当作enter()方法的返回值,赋值给scq

使用这种方法的好处是将业务逻辑代码部分与异常处理代码部分进行分离,达到代码的解耦目的,例如:

import contextlib
@contextlib.contextmanager
def ze():
try:
yield
except Exception as e:
print(“error”, e)
a = 1
b = 0
with ze():
a / b
x = 1
y = 0
with ze():
x / y
而其原本的代码重复性比较高,并且异常处理代码和业务逻辑代码混在一起:

a = 1
b = 0
try:
a / b
except Exception as e:
print(“error”, e)
x = 1
y = 0
try:
x / y
except Exception as e:
print(“error”, e)

方法三:利用含有close()方法的类创建上下文管理器

1.一个含有close()方法的类,根据逻辑,可以这样实现上下文管理器

class A(object):
def t(self):
print(“t”)
def close(self):
print(“释放代码”)
def enter(self):
return self
def exit(self, exc_type, exc_val, exc_tb):
self.close()
with A() as a:
a.t()
先执行enter()方法,返回A类的实例对象给a,再执行语句体,使用a调用方法t(),最后自动执行exit()方法,在其中调用close()方法,释放代码

2.使用contextlib模块的closing()函数,可以是含有close()方法的类直接变成上下文管理器

import contextlib
class A(object):
def t(self):
print(“t”)
def close(self):
print(“释放代码”)
with contextlib.closing(A()) as a:
a.t()
(6)多个上下文表达式的操作

python2.7之前:contextlib.nested()

import contextlib
with contextlib.nested(open(“a.txt”, “r”) , open(“a1.txt”, “w”)) as (from_file, to_file):
content = from_file.read()
to_file.write(content)
python2.7之后:嵌套或者合并

with open(“a.txt”, “r”) as from_file, open(“a1.txt”, “w”) as to_file:
content = from_file.read()
to_file.write(content)
(7)手动抛出异常–raise ExceptionType(content)

def ageSet(age):
if age <= 0 or age > 200:
raise ValueError(“不符合”)
else:
print(“小明的年龄是%d” % age)
ageSet(18)
需要注意的是,在这个异常严重影响程序整体功能实现的时候,就必须要进行手动抛出,对异常进行修改,如果异常无伤大雅,可以直接对其进行打印,这样避免因为小的异常而终止后续程序的运行

(8)自定义异常

class Xerror(Exception):
def init(self, mag, code_error):
self.mag = mag
self.code_error = code_error
pass
def str(self):
return self.mag + str(self.code_error)
def ageSet(age):
if age <= 0 or age > 200:
raise Xerror(“不符合”, 404)
else:
print(“小明的年龄是%d” % age)
try:
ageSet(-18)
except Exception as x:
print(“cunwu”, x)

由于常见异常都是继承自Exception类的,座椅这里可以自定义一个继承了Exception的子类,在向外抛出异常时,即raise Xerror(“不符合”, 404) ,可以看成是创建一个Xerror实例对象,并对其初始化属性进行赋值,然后利用str()方法对实例对象进行描述,这就是自定义异常的方法,在最后可以对抛出的异常进行捕捉


20190426

SyntaxError: Non-UTF-8 code starting with 'xc1' in file C:...xxx.py on line 8, but no encoding declared; see http://python.org/dev/peps/pep-0263/ for details
#!/usr/bin/python
#-*-coding:utf-8 -*-

print('hello world中文')
一、第一种方法
首行增加,已测试可用。
# coding=gbk
程序中出现中文,运行的时候出现如下错误:
SyntaxError: Non-UTF-8 code starting with 'xc1' in file C:...xxx.py on line 8, but no encoding declared; see http://python.org/dev/peps/pep-0263/ for details
导致出错的根源就是编码问题。
解决方案是:
     在程序最上面加上:
# coding=gbk
二、第二种方法
可以修改eclipse的编码,在Project--》properties--》resource --》text file encoding 选择other --》选择utf-8 ,应用保存即可 之后所有的中英文都不在干扰,也可以在页面第一行加上# -*- coding:utf-8 -*- 效果一样。

淘汰coding=gbk

作者:

喜欢围棋和编程。

 
发布于 分类 编程标签

发表评论

电子邮件地址不会被公开。