python 学习笔记 错误调试 文件读写

 九:错误,调试和测试
                1:错误处理:
                    在程序运行的过程中,如果发生了错误,可以事先约定返回一个错误代码,这样就知道是否有错,以及出错的原因。Python内置 try....except.....finally.....的错误处理机制
                    try:
                        print 'try...'
                        r=10/0
                        print 'result'
                    except ZeroDivisionError,e:
                        print 'except:',e
                    finally:
                        print 'finally....'
                    print 'END'
                    输出结果:
                    try....
                    except:integer division or modulo by zero
                    finally...
                    END
                    和java一样 可以用多个except 来捕捉不同类型的错误,如果没有错误发生,可以再except语句块后面加上一个else 当没有错误发生的时候会自动执行else语句
                    Python的错误 其实也是class 所有的错误类型都继承自BaseException 所以在使用except时需要注意 它不但捕捉这个类型的错误还会把子类也一网打尽。
                            try:
                                foo()
                            except StandardError,e:
                                print 'standartError'
                            except ValueError,e:
                                print 'ValueError'
                    由于ValueError是StandardError的子类 所以except永远也捕捉不到ValueError。
                    如果错误没有被捕捉 他将会一直往上抛,最后被Python解释器捕获 打印错误信息。
                    Python内置的logging模块 可以非常容易的记录错误的错误信息:
                            #err.py
                            import logging
                            
                            def foo(s):
                                return 10/int(s)
                
                            def bar(s):
                                return foo(s)*2

                            def main():
                                try:
                                    bar('0')
                                except StandardError,e:
                                    logging.exception(e)

                            main()
                            print 'End'
                通过对logging的配置 还可以将错误记录打印到日志文件中。

                抛出错误:
                    因为错误是一个class 所以捕获错误就是到改class的一个实例,因此错误是可以有意创建并且抛出的。如果要抛出错误,首先根据需要,可以定义一个错误的class选择好继承关系 然后用raise语句抛出一个错误的实例
                            #err.py
                            class FooError(StandardError):
                                pass
                
                            def foo(s):
                                n=int(s)
                                if n==0:
                                    raise FooError('invalid value:%s' % s)
                                return 10/n
                    只有在必要的时候才定义自己的错误类型 如果可以选择Python已有的内置错误类型 尽量使用Python内置错误类型。
                    raise语句如果不带参数 就会把当前错误原样的抛出,except和raise一个error 还可以把一种类型的错误转换成另一种类型的错误。 只要是合理的逻辑都可以。

                2:调试:
                    1:print
                    2:断言 assert 凡是用print来辅助查看的地方都可以用断言来代替
                            #err.py
                            def foo(s)
                                n=int(s)
                                assert n!=0,'no is zero!'
                                return 10/n
                
                            def main():
                                foo('0')
                        assert 的意思是 表达式n!=0应该是True 否则后面的代码就会出错 如果断言失败 assert 语句本身就会抛出AssertionError 启动Python解释器的时候可以用 -0参数关闭assert
                    3:logging 把print替换成logging 和assert比 logging不会抛出错误 而且还可以输出到文件
                            #err.py
                            import logging

                            s='0'
                            n=int(s)
                            logging,info('n=%d' %n)
                            print 10/n
                        logging可以 输出一段文本 运行 发现除了ZeroDivisionError 没有任何的信息 这需要在 import logging  后面添加一行配置
                            import logging
                            logging.basicConfig(level=logging.INFO)
                    4:pdb Python的调试器 让程序以单步方式运行,可以随时的查看运行状态。
                        Python -m pdb err.py
                        l 查看当前代码
                        n 单步执行代码
                        p 变量名  查看变量
                        q 结束调试 退出程序 
                    5:pdb.set_trace()
                        这个方法也是pdb 但是不需要单步执行 只需要import pdb 然后在有可能出错的地方放一个pdb.set_trace() 就可以设置一个断点  运行代码 程序会自动的在pdb.set_trace()暂停 并进入到pdb的调试环境中 可以使用p查看变量或者 使用c继续运行。

            3:单元测试:
                    单元测试时用来对一个模块,一个函数,或者一个类 进行正确性检验的测试工作。
                    比如 对于函数abs() 我们可以编写出一下几个测试用例:
                    1: 输入正数 比如1 ,1.2 0.99 期待返回值与输入相同;
                    2:输入负数  比如 -1 -1.2 -0.99 期待返回值与输入想法;
                    3:输入0 期待返回0
                    4:输入非数值类型 比如 None,【】,{} 期待抛出 TypeError
                    把上面的测试用例 放到一个测试模块中 这就是一个完整的单元测试。
                    如果单元测试通过 说明我们 这个函数能够正常工作,如果单元测试不通过 要么bug 要么测试条件输入不正确。
                    编写一个Dict类 这个类的行为和dict一致 但是可以通过属性来访问 用起来就像:
                        >>>d=Dict(a=1,b=2)
                        >>>d['a']
                        1
                        >>>d.b
                        2
                    mydict.py:
                        class Dict(dict):
                            def __init__(self,**kw):
                                super(Dict,self).__init__(**kw)

                            def __getattr__(self,key):
                                try:
                                    return self[key]
                                except:
                                    raise AttributeError(r'' 'Dict'object has no attribute '%s' '' % key)
                        
                            def __setattr__(self,key,value)
                                self[key]=value
                    单元测试:
                        import unittest
            
                        from mydict import Dict
        
                        class TestDict(unittest.TestCase):
        
                            def test_init(self):
                                d=Dict(a=1,b='test')
                                self.assertEquals(d.a,1)
                                self.assertEquals(d.b,'test')
                                self.assertTrue(isinstance(d,dict))

                            def test_key(self):
                                d=Dict()
                                d['key']='value'
                                self.assertEquals(d.key,'value')
                
                            def test_attr(self):
                                d=Dict()
                                d.key='value'
                                self.assertTrue('key' in d)
                                self.assertEquals(d['key'],'value')
                        
                            def test_keyerror(self):
                                d=Dict()
                                with self.assertRaise(keyError):
                                    value=d['empty']

                            def test_attrerror(self):
                                d=Dict()
                                with self.assertRaises(AttributeError):
                                    value=d.empty
                        编写单元测试 就是自己写一个测试类 然后从unittest.TestCase继承 
                        以test开头的方法都是测试方法 不易test开头的方法不被认为是测试方法 测试的时候不会被执行
                        对于每一类测试都要编写一个test_xxx方法 最常用断言来判断
                        最后两种断言是 期待抛出指定的error 
                        运行测试单元:
                            1:在mydict_test.py 的最后两行加上:
                                if __name__=='__main__':
                                    unittest.main()
                            2:python -m unittest mydict_test
                        可以再单元测试中编写两个特殊的setUp()和tearDown()方法 这两个方法分别在每调用一个测试方法的前后被执行。

                    4:文档测试:
                        Python的文档注释模块可以直接提取注释中的代码并进行测试
                        doctest严格按照Python交互式命令行的输入和输出来判断测试结果是否正确 只有在测试异常的时候 可以用...表示中间一大段烦人的输出
                        用doctest 来测试Dict
                        class Dict(dict):
                            ...
                            simple dict but alse support access as x.y style.
                            
                            >>>d1=Dict()
                            >>>d1['x']=100
                            >>>d1.x
                            100
                            >>>d1.y=200
                            >>>d1['y']
                            200
                            >>>d2=Dict(a=1,b=2,c='3')
                            >>>d2.c
                            '3'
                            >>>d2['empty']
                            Tracebace...
                            >>>d2.empty
                            Traceback...
            
                             def __init__(self,**kw):
                                super(Dict,self).__init__(**kw)

                            def __getattr__(self,key):
                                try:
                                    return self[key]
                                except:
                                    raise AttributeError(r'' 'Dict'object has no attribute '%s' '' % key)
                        
                            def __setattr__(self,key,value)
                                self[key]=value
                        if __name__=='__main__':
                            import doctest
                            doctest.testmod()  ..

    十 IO编程:(同步IO 和异步IO)
                    1: 文件读写:
                        在磁盘上读写文件都是有操作系统提供的 现代操作系统不允许普通的程序 直接操作磁盘
                        >>>f=open('/Users/michael/test.txt','r')
                        Python内置的open()函数 传入文件名和提示符 标示符r表示读 这样我们就成功的打开了一个文件
                        如果文件不存在 open函数就会抛出一个IOError的错误 并给出错误码和详细信息
                        如果文件打开成功 接下来就可以调用read()方法 可以一次的读取文件的全部内容 Python把内容读到内存 用一个str对象表示
                        >>>f.read()
                        'Hello,world'
                        最后一步 是调用close()方法关闭文件 文件使用完毕后必须关闭 因为文件对象会占用操作系统的资源 并且操作系统同一时间能够打开的文件数量是有限的
                        >>>f.close()
                        try:
                            f=open('D:/a.txt','r')
                            print f.read()
                        finally:
                            if f:
                                f.close()
                       可以简化为:
                        with open('D:/a.txt','r') as f:
                            print f.read()
                        调用一次f.read()将会一次性读取文件的全部内容,保险起见 可以反复调用read(size)方法 每次最多读取size个字节的内容 另外 调用readlines() 可以每次读取一行的内容
                        如果文件很小 read()一次性读取最方便 不确定文件大小 read(size)最保险 如果是配置文件 readlines()最方便
                        for line in f.readlines():
                            print(line.strip())   #把末尾的'\n'去掉
                    
                    2:file-like Object
                        像open()函数返回的这种有个read()方法的对象 在Python中统称为file_like Object 除了file外 还可以是内存的字节流 网络流 自定义流 等等 file-like Object 不要求从定义类继承 只要写个read()方法就行
                        StringIO 就是在内存中创建的file_like Object 常用作临时缓冲
                        要读取二进制文件 需要使用 ‘rb’模式打开文件即可
                        要读非ASCII编码的文本文件就必须以二进制模式打开 在解码 比如GBK编码的文件:
                        >>>f=open('/Users/lc/gbk.txt','rb')
                        >>>u=f.read().decode('gbk')
                        >>>print u
                        python 提供了一个codecs模块帮我们在读文件时自动转换编码 直接读出Unicode
                        import codecs
                        with codecs.open('/User/lc/test.txt','r','gbk') as f:
                            f.read()
                        写文件 写文件和读文件时一样的 唯一的区别就是调用的时候 传入的标示符是 ‘w’‘wb’标示读写文本文件和二进制文件
                        >>>f.open('/Users/lc/test.txt','w')
                        >>>f.write('Hello,World!')
                        >>>f.close()
                        或者使用with 语句
                        with open('Users/lc/test.txt','w') as f:
                            f.write('Hello world!')
                        使用with语句操作文件的IO是一个好习惯

                    2:操作文件和目录
                        >>>import os
                        >>>os.name
                        可以获取系统的名字信息 如果是nt 表示windows 如果是POSIX表示的是Linux
                        >>>os.uname()
                        函数可以获取系统的详细信息 但是windows不支持。
                        环境变量
                        操作系统定义的环境变量 全部保存在 os.environ dict  要获取某个环境变量的值可以调用 os.getenv('变量名')函数
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值