在Python中使用内置类型(如int
和float
时,在输入可能不可靠的情况下采用异常处理很常见:
def friendly_int_convert(val):
"Convert value to int or return 37 & print an alert if conversion fails"
try:
return int(val)
except ValueError:
print('Sorry, that value doesn\'t work... I chose 37 for you!')
return 37
使用str()
?
def friendly_str_convert(val):
"Convert value to str or return 'yo!' & print an alert if conversion fails"
try:
return str(val)
except Exception: # Some specific Exception here
print('Sorry, that value doesn\'t work... I chose \'yo!\' for you!')
return 'yo!'
我真的不喜欢使用广泛的Exception
,因为有NameError
这样的情况表示代码存在问题并且应该引发错误。我已将UnicodeError
视为候选人,但我不确定str()
是否会导致该问题(与foo.encode()
和foo.decode()
相对应更容易理解)并且会喜欢一个输入(如果有的话)会触发它的例子。
总结:即使输入不可靠,使用str()
而没有try
/ except
块通常是否安全?
答案 0 :(得分:2)
总结:即使输入不可靠,使用
str()
而没有try
/except
块通常是否安全?
这取决于我们正在谈论什么样的输入。您已经在Python 3中标记了这个问题,因此您不必担心Python 2和Unicode输入所带来的UnicodeEncodeErrors,但您接收的对象可以做很多事情。 __str__
或__repr__
中的任何内容,几乎可以引发任何异常。例如,
In [18]: import weakref
In [19]: class Foo(object): pass
In [20]: str(weakref.proxy(Foo()))
---------------------------------------------------------------------------
ReferenceError Traceback (most recent call last)
<ipython-input-20-396b2ab40052> in <module>()
----> 1 str(weakref.proxy(Foo()))
ReferenceError: weakly-referenced object no longer exists
答案 1 :(得分:1)
在这方面,str
和int
之间存在巨大差异。 int
肯定会提升TypeError
和ValueError
。
据我所知,str
可以为普通对象引发的唯一例外是UnicodeEncodeError
:
>>> s = u"a\xac\u1234\u20ac\U00008000"
>>> str(s)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
UnicodeEncodeError: 'ascii' codec can't encode characters in position 1-4: ordinal not in range(128)
这只发生在python2.x上。
当然,我可以轻松地创建一个失败的类,几乎可以想象任何异常:
>>> class MyError(Exception):
... pass
...
>>> class Foo(object):
... def __str__(self):
... raise MyError
...
>>> f = Foo()
>>> str(f)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 3, in __str__
__main__.MyError
在大多数情况下,我会质疑一些隐含的假设,即此时需要处理所有异常 。通常,最好只处理您知道如何处理的异常。在这种情况下,由于用户将垃圾放入函数中而发生的异常异常应该在垃圾进入的级别处理 - 而不是在函数本身内。捕获错误并返回一些可能是无意义的值对于调试问题等不会有太大的帮助。
答案 2 :(得分:1)
由于你提出的担忧,我会做except Exception as e:
。 {3}是Python 3中针对“正常”异常的通用“全能”(除了因为进程获取信号而导致的“系统级”异常,Exception
等)。
如果我是你,我至少会记录实际的异常(在上面的例子中为KeyboardInterrupt
),看看实际发生了什么(你的代码通过e
默默地删除了实际的异常对象)。