pylint 1.4在所有C扩展上报告E1101(no-member)错误

56

我们长期以来一直是pylint的粉丝。它的静态分析已经成为我们所有Python项目中至关重要的一部分,并节省了大量时间来追踪难以捉摸的错误。但是从1.3升级到1.4后,几乎所有编译的C扩展都会产生E1101(未知成员)错误。

之前在pylint 1.3下完美运行的项目现在会对几乎每个C扩展成员都报告E1101错误。我们不得不禁用E1101错误,但这实质上降低了pylint的有用性。

例如,这是lxml包的完全有效使用:

r"""valid.py: demonstrate pylint 1.4 error"""
from lxml import etree
print etree.Element('mydoc')

运行这个代码通过pylint,它会报告:

$ pylint -rn valid.py
No config file found, using default configuration
************* Module valid
E:  3, 6: Module 'lxml.etree' has no 'Element' member (no-member)

但这是完全有效的:

$ python valid.py
<Element mydoc at 7fddf67b1ba8>

这里变得真的很奇怪。只有极少数的C扩展似乎能够通过pylint正常工作,例如:

r"""valid2.py: this one works fine"""
import sqlite3
print sqlite3.version

$ pylint -rn valid2.py
No config file found, using default configuration

我的问题是,有没有其他人见过这种情况?如果是这样,你愿意分享你的解决方法吗?

我们尝试创建插件来抑制这些警告(http://docs.pylint.org/plugins.html#enter-plugin),但我们很难理解文档 - astroid基类非常复杂,我们也无法理解它。

为了得到额外的奖励分数(和我们永恒的感激),我们希望了解在pylint中发生了什么变化。我们将很乐意修复代码(或至少发布最佳实践文档给C扩展作者),以满足pylint

平台细节

$ pylint --version
No config file found, using default configuration
pylint 1.4.0,
astroid 1.3.2, common 0.63.2
Python 2.7.5 (default, Jul  1 2013, 18:09:11)
[GCC 4.4.7 20120313 (Red Hat 4.4.7-3)]
4个回答

77

发布问题后不久,我找到了答案。这项更改实际上是出于安全考虑而进行的。Pylint导入模块以有效识别有效的方法和属性。决定不导入不属于Python标准库的C扩展是一种安全风险,可能会引入恶意代码。

这是在Astroid 1.3.1版本发布时完成的。https://mail.python.org/pipermail/code-quality/2014-November/000394.html

只有来自可信源(即标准库)的C扩展会被加载到正在检查的Python进程中,以从实时模块构建AST。

如果您想在导入非标准库C扩展的项目上使用pylint,则有四个解决方案。

1) 使用命令行选项--unsafe-load-any-extension=y禁用安全性。此功能未记录,属于隐藏选项。https://mail.python.org/pipermail/code-quality/2014-November/000439.html

2) 使用 pylint.rc 设置 unsafe-load-any-extensions=yes 禁用安全性。这比选项1更可取,并且在默认的 pylint.rc 文件(使用--generate-rcfile创建)中包含完整的文档。

3) 在 pylint.rc 文件中使用 extension-pkg-whitelist= 选项具体列出您信任的要由pylint加载的软件包或模块名称。

4) 创建一个插件来操作AST(我不知道如何执行此操作,但是这经常在pylint邮件列表上讨论)。

我们选择了Option 3。我们将以下行添加到我们的项目 pylint.rc 文件中:

extension-pkg-whitelist=lxml

非常感谢。不过,我必须指出,选项3似乎无法与某些STL包一起使用,例如multiprocessing - 4ae1e1
对于#4,这份文档似乎直接解决了如何修复错误的“no-member” - http://docs.pylint.org/plugins.html - Spain Train
这是最新的链接:https://docs.pylint.org/en/1.8/how_tos/transform_plugins.html - Fletch
更好的链接到最新文档:https://pylint.readthedocs.io/en/latest/how_tos/transform_plugins.html - Fletch
3
现在它被称为 extension-pkg-allow-list - Luciano
显示剩余5条评论

8

@user590028,非常感谢您的回答!我也遇到了使用win32api、win32evtlog、win32file、win32gui和win32process库出现的问题,而您提供的解决方案很有效。

我还想分享一个方法,在调用pylint时将白名单包作为参数传递:

pylint --extension-pkg-whitelist=win32api,win32evtlog,win32file,win32gui,win32process myfile.py

1
非常感谢你。顺便提一下,extension-pkg-whitelist 是选项3,也是我们选择的选项。 - user590028
2
我只是想确保人们知道你也可以将它作为命令行参数传递给pylint。 - twasbrillig

5
对于使用VS Code的用户来说,要找到放置命令的位置有点棘手,因为我找不到可执行文件。
在VS Code中:
  1. 点击“文件”>“首选项”>“设置”。
  2. 在左窗口中滚动到“Python配置”。
  3. 在右窗口中滚动到“Python Linting: Mypy Args”。
  4. 点击“在settings.json中编辑”链接。
  5. 编辑json以包括:"--extension-pkg-whitelist="。
我不得不这样做,因为PyLint无法从我的Windows命令行中执行...

我成功地在VS Code中使用了命令行参数来运行pylint,方法是编辑用户设置文件并添加以下代码: "python.linting.pylintArgs": ["--unsafe-load-any-extension=y"], - John Forbes

1

如果您正在使用Mac上的VS Code,则需要执行以下操作才能编辑settings.json文件:

  1. 单击Code(即位于“文件”选项卡左侧的Visual Studio Code选项卡)->首选项->设置
  2. 向下滚动到扩展并在列表中单击Python。
  3. 单击任何一个在settings.json中编辑链接。这将打开settings.json以进行编辑。
  4. 添加行"python.linting.pylintArgs": ["----extension-pkg-whitelist=1xml"]

这里是 {… "pylint.args": […, --extension-pkg-allow-list=posix_ipc ]} - Alex Cohn

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