知乎:https://www.zhihu.com/people/monkey.d.luffy Android高级开发交流群2: 752871516
全部博文(315)
分类: Python/Ruby
2012-02-22 21:30:15
异常
至于异常挺不简单的,我认为!我们都知道国外对于软件测试的投入远远 高于中国,所以才会有很多好的软件!下面是比较基本的测试例子:
From:
#file: tryExcept.py
#!/usr/bin/env python
'''
-BaseException
|- KeyboardInterrupt
|- SystemExit
|- Exception
|- (all other current built-in exceptions)
'''
def safe_float(obj):
try:
retval = float(obj)
except ValueError:
retval = 'Could no convert non-number to float'
except TypeError:
retval = 'Object type cannot be converted to float'
return retval
def safe_float2(obj):
try:
retval = float(obj)
except BaseException, e: #e save the error information; generally e is tring;
retval = 'Object must be number\n' + 'system: ' + str(e)
#else:
#pass
return retval
def safe_float3(obj):
try:
retval = float(obj)
except (ValueError, TypeError), e:
retval = str(e)
else:
pass #TODO
finally:
retval = 'This part must be Done!'
return retval
def safe_float4(obj):
try:
retval = float(obj)
finally:
retval = 'This part must be Done!'
pass #can handler file.close()
return retval
if __name__ == '__main__':
print safe_float('123')
print safe_float('abc')
print safe_float({'abc': 'Dict'})
print safe_float2({'abc': 'Dict'})
print safe_float3({'abc': 'Dict'})
当然这些只是皮毛,后面还有很多关于上下文管理相关的异常实例,像with语句,断言的知识,等等........
至于这个上下文和上下文管理,我想还是有必要了解下:
上下文:
看到这里想到学习c的时候提到的进程上下文?
进程上下文实际上是进程执行活动的全过程的静态描述。(感觉好像是理论的东西)。我们把已经执行过的进程指令和数据在相关寄存器与堆栈中的内容称为上文,把正在实现的指令和数据在寄存器和堆栈中的内容成为正文,把待执行的指令和数据在寄存器与堆栈中的内容成为下文。
具体的就是包括通用寄存器,状态寄存器,计数寄存器,数据集,各种堆栈PCB结构等。说到寄存器,在学习arm的时候,老师不是常说需要保存进程上下文,然后恢复,就用到了以上概念!还有很多更深的就不懂了。
上下文就是一种属性的有序序列,他们为驻留在环境内的对象定义环境。在对象激活的过程中创建上下文,对象被配置为要求某些自动服务,如同步,事务,实时激活,安全性等等。多个对象可以驻留在一个上下文内,也是根据上下文理解这个意思。还是不太理解?........看来要实践才能掌握....
上下文管理:
上网查了下;关于WCF(windows context form)的,在应用开发当中,我们需要经常设置一些上下文信息,这些上下文信息一般是基于当前会话,比如用户登录的个人信息;或者基于当前方法调用的栈,比如在同一次调用中涉及的多个层次之间的数据。我们需要创建相应的类,组建或者什么什么来管理它,以便让程序更加健壮!
最后,还是要说这点是不够的,要深入,还是需要很长时间的。还是来分析一个列子,加深下理解就好,实在不理解算了!
自己创建异常:(我按照python核心编程的pdf文件来写,发现有问题,复制的又不好使,自己调了半天?悲剧啊,有个地方需要注意:
就是在用mktemp()这个方法的时候要注意,需要tempfile.mktemp()这种点标识法才行,至少我的是这样的!因为我们是用import 来导入的,而不是from xxx import xxx
)
#file: myexc.py
#这是启动脚本,可以省去,不过环境变量要设置好!
#!/usr/bin/env python
#模块导入,后面会用到
import os, socket, errno, types, tempfile
#以下两个是我们新派生的两个异常类,都是基于I/O的!
#一个是网络相关的,一个是文件相关的;处理是忽略掉,避免程序运行时
”死掉“
class NetworkError(IOError):
pass
class FileError(IOError):
pass
#更新异常的参数,这是socket用的,其实和文件的异常参数更新是类似的
def updArgs(args, newarg=None):
if isinstance(args, IOError):
#instance就是说判断是否是一个实例,具体含义,再查?后来看了以前练习的代码:(如果是属于IOError,就更新我们需要的异常信息参数,过滤下而已)
/-----------------------------------------------------------------------------------
#if isinstance(num, (int, long, float, complex)):
#print 'a number of type:', type(num).__name__
#__name__ can translate
#else: print 'not a number at all!'
/-----------------------------------------------------------------------------------
myargs = []
myargs.extend([arg for arg in args])
else:
myargs = list(args)
if newarg:
myargs.append(newarg)
return tuple(myargs)
#在打开文件时调用,目的是为了得到表示权限相关的异常;这里我们利用字典的方式来得到文件权限的参的数列表
def fileArgs(file, mode, args):
if args[0] == errno.EACCES and \
'access' in dir(os):
perms = ''
permd = {'r': os.R_OK, 'w': os.W_OK,
'x': os.X_OK}
pkeys = permd.keys()
pkeys.sort()
pkeys.reverse()
for eachPerm in 'rwx':
if os.access(file, permd[eachPerm]):
perms += eachPerm
else:
perms +='-'
if isinstance(args, IOError):
myargs = []
myargs.extend([arg for arg in args])
else:
myargs = list(args)
myargs[1] = "'%s' %s (perms: '%s')" % \
(mode, myargs[1], perms)
myargs.append(args.filename)
else:
myargs = args
return tuple(myargs)
def myconnect(sock, host, port):
try:
sock.connect((host, port))
except socket.error, args:
myargs = updArgs(args) #conv inst2tuple
if len(myargs) == 1:
myargs = (errno.ENXIO, myargs[0])
raise NetworkError, \
updArgs(myargs, host + ':' + str(port))
def myopen(file, mode='r'):
try:
fo = open(file, mode)
except IOError, args:
raise FileError, fileArgs(file, mode, args)#myopen产生的异常相关信息就这样传个了fileArgs()函数
return fo
def testfile():
file = tempfile.mktemp()
f = open(file, 'w')
f.close()
#改变文件的不同的权限eachTest[0]的value就是对应的权限,然后哦我们在尝试用eachTest[1]的value对应的打开模式去打开它,最后得到相关异常信息,最后调用args.__class__.__name__得到异常名字,和args一块显示出来
for eachTest in ((0, 'r'), (0100, 'r'),(0400, 'w'), (0500, 'w')):
try:
os.chmod(file, eachTest[0])
f = myopen(file, eachTest[1])
#在调用自定义函数mpopen()的时候,我们得到了args,自然会传给fileArgs(),因为myopen()调用了它,所以字符串就得到了些许修改,也就是可以按我们自己的打印方式来打印!所以调用关系是这样的,这样我们才更加明白思路!
except FileError, args:
print "%s: %s" % \
(args.__class__.__name__, args)
else:
print file, "openned ok ... perm ignored"
f.close()
os.chmod(file, 0777) #enable all perms
os.unlink(file)
#相当于os.remove()
def testnet():
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
for eachHost in ('deli', 'www'):
try:
myconnect(s, 'deli', 8080)
except NetworkError, args:
print "%s: %s" % \
(args.__class__.__name__, args)
if __name__ == '__main__':
testfile()
testnet()
Result:(我想应该差不多这样吧)
huanglei@huanglei-laptop:~/python/tryExcept$ python myexc.py
FileError: [Errno 13] 'r' Permission denied (perms: '---'): '/tmp/tmpSCWX1Z'
FileError: [Errno 13] 'r' Permission denied (perms: '--x'): '/tmp/tmpSCWX1Z'
FileError: [Errno 13] 'w' Permission denied (perms: 'r--'): '/tmp/tmpSCWX1Z'
FileError: [Errno 13] 'w' Permission denied (perms: 'r-x'): '/tmp/tmpSCWX1Z'
NetworkError: [Errno -5] No address associated with hostname: 'deli:8080'
NetworkError: [Errno -5] No address associated with hostname: 'deli:8080'