在Python中使用内置str()类型的潜在异常

时间:2016-07-14 17:14:24

标签: python string python-3.x exception-handling built-in

在Python中使用内置类型(如intfloat时,在输入可能不可靠的情况下采用异常处理很常见:

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块通常是否安全?

3 个答案:

答案 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)

在这方面,strint之间存在巨大差异。 int肯定会提升TypeErrorValueError

据我所知,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默默地删除了实际的异常对象)。