本文涉及的主要程序有 Python 3.6, VS Code 1.33.1 。

Python 扩展为在 VS Code 中编辑 Python 代码提供了许多功能,代码补全、智能提示、格式化代码、代码重构等。这些基础功能一般自己摸索下就都会用,所以就不浪费文字在一些概念上了,有需要的可以看上面的连接。本文我会写一点经常遇到的问题,以及能提升写代码体验的方法。

格式化代码

先说个简单的,VS Code 可以自动格式化代码,使用方法很傻瓜式,在 .py 右键选择,弹出红框点击安装相应的库,VS Code 就会自己配置好,之后再右键就能格式化了。


这其实没什么好说的,不过真正的问题是,VS Code 需要把 autopep8 安装到你当前的 pythonPath 上,如果你用虚拟环境,那每一个新建的环境都要安装一遍 autopep8,这显然太麻烦,毕竟你几乎不会需要不同版本的 autopep8 。另外,当你打包依赖时pip freeze > requirements.txt ,会把项目不直接依赖的库也打包进去,这样完全就是多余的。

我们可以让所有项目用一个全局的 autopep8,一行配置就可以省很多事,如下:

.vscode\settings.json
{
"python.formatting.autopep8Path": "/path/to/Python/Scripts/autopep8.exe",
}

代码补全与智能提示

VS Code 为当前工作文件夹中的所有文件,以及安装在标准位置的 Python 包提供了代码补全和智能提示 。默认使用的是 Jedi ,如果设置了python.jediEnabled=false,会使用 Microsoft Python Language Server,后者目前 bug 多,不建议使用。

VS Code 收集代码的范围是基于当前工作区文件夹,和settings.json 中的 python.pythonPath 参数而定的。如果指定了虚拟环境,有的标准库不会复制进虚拟环境的 Lib 文件夹里,故而无法正常进行代码提示以及源码导航。还有如果你引用的项目既不在工作区内,也不在 Python 库文件夹里,VS Code 自然无法知道它在哪。这时候需要提供额外的路径去搜寻代码,如下:

.vscode\settings.json
{
"python.autoComplete.extraPaths": ["any/path"],
}

由于 Python 动态的特性,以及变量不需要指定类型的特性, 所以 Python 的代码提示有天生的缺陷。VS Code 大部分情况下可能无法确定一个变量或属性的类型,也就难以进行相应的提示。

还好我们可以利用Type Hint帮助 VS Code 更好的提示代码,比如一个经典的例子,写 django 视图时一个必填的参数是 request ,用上 Type Hint 就能提示出 request 的属性和方法:


虽然虽然用 Type Hints 还是可以弥补类型上的缺失,不过 Python 3.5 才开始支持。而且我想,使用 Python 的人大部分都是不想被类型束缚的吧。至少我个人觉得如果写 Python 都得一个个定义类型,那还不如去写 Java。对我来说真正用到 Type Hints 的时候比较少。

即使 Python 的静态类型可以提供一定的代码提示能力,但是遇上动态类型就无法工作了,动态添加的属性,动态生成的类,动态导入的类,等等但凡利用里动态特性的代码,几乎都无法正常给出代码提示,这可以说是动态语言在 IDE 支持上天生的软肋。

我们自己或许很少写这种利用动态特性的代码,但是很多第三方库都会用,比如 django 的 Model.objects,这个django ORM 必用的属性在 VS Code 上几乎没法正常地给出提示。问题是这个不仅用的多,他的用法也很多,很难全记住,于是很多时候不得不对照这文档去写查询语句。

遇上这样的情况,正常的代码提示是无法解决问题的,不过也不是不能解决,要给出足够的代码提示还需要用到调试大法。如何利用调试来辅助写代码这点,我下一篇文章再写。

静态检查

VS Code 默认的静态检查工具是 pylint ,也是在settings.json里修改相关设置,下面是我常用的配置:

{
"python.linting.pylintPath": "global/path/to/pylint.exe",
"python.linting.pylintArgs": [
// https://pylint.readthedocs.io/en/latest/technical_reference/features.html
"--disable",
"no-member, arguments-differ, unused-argument, attribute-defined-outside-init, broad-except, missing-docstring, invalid-name, no-self-use, too-few-public-methods, too-many-ancestors, too-many-instance-attributes, too-many-arguments, line-too-long, protected-access",
"--init-hook",
"import sys; sys.path.extend(['${workspaceFolder}/venv/Lib/site-packages',]);"
],
}

python.linting.pylintPath 的作用是指定 pylint 的路径,如果不填则默认使用当前工作区指定的 Python 环境中的 pylint。如果虚拟环境多的话,每一个环境中都要安装一遍 pylint,很麻烦,不如全局使用同一个 pylint。

使用全局 pylint 还有一点要注意,因为不同环境中安装的包不一样,必须在静态检查是引入相关的环境下的包,在 --init-hook中把虚拟环境下第三方包的路径导入sys.path即可。

静态检查默认的检查项比较苛刻,如果放任不管会导致各种波浪线,严重影响心情。如上所示,用 --disable 参数指定忽略的检查项即可消除。波浪线的提示信息中会显示检查项的名称,把不需要的添加到设置中,即可定制自己的静态检查范围,更多内容可查看 pylint 检查项。

相关文章:Fossen:Python in VS Code:环境配置zhuanlan.zhihu.comFossen:Python in VS Code:编辑代码zhuanlan.zhihu.comFossen:Python in VS Code:调试中开发zhuanlan.zhihu.com