zoukankan      html  css  js  c++  java
  • Python-警告处理

    python 下Warning的使用

    起因是这样的,当我使用pymysql模块执行建表的sql语句时获,在控制台输出了红色的消息,但是程序并没有终止而是继续运行了

    sql语句如下:

    CREATE TABLE IF NOT EXISTS test(age int);
    

    整体代码:

    import pymysql
    conn = pymysql.connect(
        user= "root",
        password="",
        database="test"
    )
    
    c = conn.cursor()
    c.execute("create table if not exists abc(age int)")
    

    得到的警告信息如下:

    """
    NoneType: None
    /Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/pymysql/cursors.py:170: Warning: (1050, "Table 'abc' already exists")
      result = self._query(query)
    """
    Process finished with exit code 0
    

    sql语句是如果表存在则放弃创建,这意味着这个警告是应该的,并没有逻辑上的错误,但是这个红色的消息,让人看着不爽,于是找到了如下解决方案:

    from warnings import filterwarnings
    filterwarnings("ignore",category=pymysql.Warning)
    

    问题得到解决,作为强迫症患者,必须在深入研究一下,得出以下结论:

    warning模块中主要的两个方法

    1.warn

    该方法用于输出一个警告信息 
    #参数一: message 表示警告的详细信息
    #参数二: category 类别,需要一个类作为参数,该类必须是Warning的子类,Warning类是Exception的子类,用于给警告设置一个具体的类型
    #参数三: stacklevel 指定调用栈的层级,用于确定要从哪一级获取行号
    #参数四: 没研究
    

    stacklevel在源码中的调用:

    image-20190722221550778

    上述代码获得一个frame,用于获取行号

    image-20190722221746845

    由以上源码可以get到一个小技能即获取行号

    python获取行号:

    import sys
    f = sys._getframe() # f 是一个对象class为 frame 但是该类无法直接访问,猜想是系统底层隐藏的毕竟与解释器核心数据相关
    print(f.f_lineno) # f_lineno就是用于获取行号的属性
    
    """
    在源码中可以看到_getframe函数是可以给一个整型参数的,
    经过测试,得出结论,该参数用于,指定从栈的哪一个位置获取行号,
    """
    
    #测试代码:
    1 import sys
    2 def task():
    3    f = sys._getframe(2)
    4    print(f.f_lineno)
    5 
    6 def task2():
    7    task()
    8 
    9 task2()
    
    """
    0表示从当前位置,即执行_getframe的地方 
    1表示获取上一级调用位置的行号 即第7行
    2表示上上级 即第9行 以此类推...  
    """
    

    2.filterwarnings

    该方法用于过滤警告信息 
    #参数action:    表示如何处理这个警告
    							 可选的值 "error", "ignore", "always", "default", "module","once"
      						 error会将警告作为异常抛出
        					 ignore表示忽略该类警告不会打印
          				 once表示该相同类型相同消息的警告仅打印一次
    #参数category:  需要一个类,表示是要过滤的警告类别
    #参数module:    需要一个模块,表示是要过滤的模块名称
    #参数lineno:		一个整型,表示要过滤哪一行的警告 0表示所有行  其他值貌似没有作用
    

    意外发现

    在查看源码是,发现了一个用于表示警告消息的类

    image-20190722230232847

    该类非常简单,就是保存了一些警告信息,然后覆盖了 __str__函数,用于自定义字符串形式

    其中的初始化函数引起了我的注意,分析了一下,发现这个写法不错,可以简化初始化中的属性赋值操作于是做了一下实验:

    # 通用的类初始化方法
    class Person():
        def __init__(self,a,b,c):
            for k,v in locals().items():
                if k != "self":
                    setattr(self,k,v)
    
    p = Person(1,2,3)
    print(p.a)
    print(p.b)
    
    

    该方法最大的好处在于,无论初始化方法中需要多少参数都可以一一赋值,对于初始化参数多的类非常友好;

    其原理是通过locals()来获取函数中的局部变量的字典形式,然后遍历字典,排除self之后其他的都设置为self的属性,用形参的名字作为熟悉名,大大减少了一堆重复的赋值代码!

    否则你的代码可能是这样的:

    class Person():
        def __init__(self,a,b,c,d):
            self.a = a
            self.b = b 
            self.c = c
            self.d = d
    
    p = Person(1,2,3,4)
    print(p.a)
    print(p.b)
    print(p.c)
    

    如果参数特比多的话,你懂的......

  • 相关阅读:
    MVP模式与MVVM模式
    webpack的配置处理
    leetcode 287 Find the Duplicate Number
    leetcode 152 Maximum Product Subarray
    leetcode 76 Minimum Window Substring
    感知器算法初探
    leetcode 179 Largest Number
    leetcode 33 Search in Rotated Sorted Array
    leetcode 334 Increasing Triplet Subsequence
    朴素贝叶斯分类器初探
  • 原文地址:https://www.cnblogs.com/yangyuanhu/p/11229128.html
Copyright © 2011-2022 走看看