【问题标题】:How to statically determine whether a source file supports python 3, for flake8?对于 flake8,如何静态确定源文件是否支持 python 3?
【发布时间】:2026-02-15 06:40:02
【问题描述】:

如何静态判断 Python 源文件是否支持 Python 3?

这个问题可能无法像那里所说的那样回答,所以我会更具体:

我的应用程序是选择一个不会产生虚假 SyntaxErrors 的 flake8 版本来运行。出于这个原因,我正在寻找(至少)一些启发式方法来告诉我是应该运行 flake8 的 Python 3 副本还是 Python 2 副本。

我正在使用我的编辑器中的 flake8,它会在我输入时显示 lint 错误,我最担心的是有时我会丢失命名错误(例如 F821),这是 pyflakes/flake8 的副作用认为某些东西是语法错误,实际上是正确的语法:当它遇到语法错误时(可以理解)似乎放弃了命名错误之类的东西。

【问题讨论】:

  • 这几乎是不可能的。要测试的代码路径太多。
  • if re.findall("print[^(]+['\"],file_text) > 0:print "PY2" ...虽然它可能不能保证它总是正确的...
  • @JoranBeasley: from __future__ import print_function,或者只是使用print(...) 作为单个值的理所当然的事情。
  • bleh 是的,好吧...我知道它会以多种方式失败...(这就是为什么它不是答案)

标签: python python-3.x flake8 pyflakes


【解决方案1】:

这几乎是不可能的。要测试的代码路径太多了。

此外,可以编写代码以在 Python 2 和 Python 3 上运行,flake8 并不总是喜欢使这成为可能的技巧,除非项目专门使用 flake8 进行测试并标记此类网站被排除在外。因此,您可能会遇到 误报(在 Python 2 和 Python 3 版本的 flake8 中都有错误),或者代码只会在 Python 2 和 3 上运行而不会出现任何警告。

您可以改用tox 来管理给定项目的版本支持;让 tox 弄清楚要使用什么 flake8 命令(可能是多个):

[tox]
envlist = py27,py35,flake8-27,flake8-35

# ...
[testenv:flake8-27]
basepython=python2.7
deps=flake8
commands=
flake8 projectdir

[testenv:flake8-35]
basepython=python3.5
deps=flake8
commands=
flake8 projectdir

并使用tox -e flake8-27tox -e flake8-35

【讨论】:

  • 这里麻烦的是 flake8 似乎停止发射例如F821 未定义名称——这通常是 pyflakes/flake8 发送的天赐之物——当它遇到 SyntaxError 时。那么,在处理 2 对 3 时,似乎会默默地丢失非常有用的功能?对这个具体问题有什么建议吗?
  • @CroadLangshan:一个 SyntaxError 异常使整个文件无效;该文件无法解析为任何允许进一步分析的内容。恐怕对此无能为力。 flake8 没有退出代码吗?
【解决方案2】:

如果您只关心SyntaxError(您在问题中特别提到),您可以简单地尝试使用 Python 2 和 3 编译文件:

python -m compileall
python3 -m compileall

如果这些命令中的任何一个失败,您至少知道该代码不适用于该 Python 版本。反过来当然不正确:如果代码在特定版本的 Python 中编译,那并不能保证它在该版本的 Python 中可以正常工作。它只是告诉你没有SyntaxErrors。

【讨论】:

  • 我知道您在使用eval()exec() 时仍然会遇到语法错误,因此无需在评论中指出这一点。 :)