Reputation: 60054
For some reason, pylint
1.6.4 (astroid 1.4.9) does not like this:
try:
some_package.their_function()
except Exception as ex:
if ex.message.startswith(...):
...
It complains:
error (E1101, no-member, feed_sentiment) Class 'message' has no 'startswith' member
I find this surprising because:
>>> type(Exception("foo").message)
<type 'str'>
>>> Exception("foo").message.startswith
<built-in method startswith of str object at 0x10520d360>
I think this is a bug in pylint
.
However, am I doing something wrong? What is the "pythonic" way here?
PS. Yes, I know that the right way is to define my own exception subclass, but I have no control over some_package
.
PPS. Yes, I know I can annotate the code with pylint: disable=no-member
.
Upvotes: 5
Views: 487
Reputation: 152775
The pythonic way would be to convert the ex
to a str
explicitly because that also converts the message to a string:
try:
some_package.their_function()
except Exception as ex:
if str(ex).startswith(...): # or "if something in str(ex)":
The problem with Exception.message
is that it may not be a 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
It's good style and highly advisable that you use str
s as message but that is by no means guaranteed!
Upvotes: 0
Reputation: 23243
This is indeed a bug in astroid
- a pylint
's internal library used for building abstract syntax trees and value inference.
import astroid
node = astroid.builder.parse("""
ex = Exception()
msg = ex.message
""")
print list(node.locals['msg'][0].infer())
Output from this code snippet is:
[<ClassDef(message) l.0 [exceptions] at 0x34aadd0>, <ClassDef(message) l.0 [exceptions] at 0x3482cb0>]
Output means that message
attribute on exception instance is inferred as custom class definition, and not string instance.
Thanks for submitting a bug!
Upvotes: 1