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

Potential Exceptions using builtin str() type in Python

在 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() 更容易理解)并且会喜欢什么输入的例子,如果有的话,会触发它。

总结:即使输入不可靠,在没有 try / except 块的情况下使用 str() 通常是否安全?

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 失败,几乎可以想象到任何异常:

>>> 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

在大多数情况下,我会质疑一些隐含的假设,即所有异常 都需要 在此时处理。一般来说,最好只处理您知道如何处理的异常。在这种情况下,由于用户将垃圾放入函数而发生的奇异异常可能应该在垃圾进入的级别处理——而不是在函数本身内。捕获错误并返回一些可能无意义的值对调试问题等不会有太大帮助。

In summary: Is it generally safe to use str() without a try / except block even with unreliable input?

这取决于我们谈论的是哪种输入。您已将此问题标记为 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

考虑到您提出的问题,我愿意 except Exception as e:Exception 是 Python 3 中的通用 "catch-all",用于 "normal" 异常(除了 "system-level" 由进程获取信号、KeyboardInterrupt 等引起的异常)。

如果我是你,我至少会记录实际的异常(e 在我上面的例子中),看看实际发生了什么(你的代码通过 except Exception:).