pylint: 类“message”没有“startswith”成员

5

由于某些原因,pylint 1.6.4 (astroid 1.4.9) 不喜欢这个:

try:
    some_package.their_function()
except Exception as ex:
    if ex.message.startswith(...):
        ...

它抱怨:

error (E1101, no-member, feed_sentiment) Class 'message' has no 'startswith' member

我觉得这很惊讶,因为:

>>> type(Exception("foo").message)
<type 'str'>
>>> Exception("foo").message.startswith
<built-in method startswith of str object at 0x10520d360>

我认为这是pylint中的一个错误
但是,我做错了什么吗?这里有没有“Pythonic”的方法?
附注:是的,我知道正确的方法是定义自己的异常子类,但我无法控制some_package
另外,是的,我知道我可以使用pylint:disable = no-member来注释代码。

你能包含pylint/astroid的版本吗? - Łukasz Rogalski
@ŁukaszRogalski: 已编辑 (pylint 1.6.4,astroid 1.4.9 Python 2.7.13(默认值,2016年12月19日,08:29:22)[GCC 4.2.1兼容的Apple LLVM 8.0.0(clang-800.0.42.1)]) - sds
顺便提一下:message已经被弃用(自Python2.6起)。您可以简单地使用message = str(ex)(或unicode(ex))来实现相同的功能(在Python2.x中,message = ex.args [0]避免了混合Unicode / str时出错)。 - Bakuriu
@Bakuriu: 那你认同MSeifert的回答,是吗? - sds
2个回答

1

这确实是 astroid 中的一个漏洞 - 这是 pylint 内部库,用于构建抽象语法树和值推断。

import astroid

node = astroid.builder.parse("""
    ex = Exception()
    msg = ex.message
""")
print list(node.locals['msg'][0].infer())

这段代码片段的输出如下所示:

...

(保留HTML格式)。
[<ClassDef(message) l.0 [exceptions] at 0x34aadd0>, <ClassDef(message) l.0 [exceptions] at 0x3482cb0>]

输出意味着异常实例上的message属性被推断为自定义类定义,而不是字符串实例。
感谢您提交错误!

谢谢!我需要将我的错误报告移动到astroid包吗? - sds
@sds 我们会在内部处理这个问题 ;)。再次感谢您提交问题报告。 - Łukasz Rogalski
我不确定这是否是一个 Bug,因为在 Python 中没有强制 message 必须是字符串的保证(请参见我的答案,我猜你已经给它点了踩)。如果你(或 pylint)能够推断出它必须是一个字符串,那么它可能有点错误,但缺乏保证绝对是一个缺点。 - MSeifert

0
“Pythonic”的方式是显式地将“ex”转换为“str”,因为这样也会将消息转换为字符串:
try:
    some_package.their_function()
except Exception as ex:
    if str(ex).startswith(...):  # or "if something in str(ex)":

Exception.message 的问题在于它可能不是一个 str 类型:

>>> try:
...     raise ValueError(1.2)
... except Exception as ex:
...     print ex
...     print type(ex.message)
...     print repr(str(ex))  # force it to be a string
...     print hasattr(ex.message, 'startswith')
ValueError(1.2,)
<type 'float'>
'1.2'
False

良好的编程风格和高度建议你使用 str 作为消息,但这绝不是保证!


我已经更清楚地指出Exception.message可能根本不是一个字符串(因此可能没有startswith方法)。没有理由给我点踩! - MSeifert

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接