介绍一个强大实用的 Python 工具 isort,可以把我们代码中的 import 部分分类、排序,实现格式化,优化统一代码风格,利于团队协作。
本文应该是目前中文社区中介绍 isort 最全面详细的文章(七千字长文,对相当篇幅的官方文档进行了中文翻译),直接点赞、收藏、阅读、退出一气呵成即可。
可以到我的博客查看原文,阅读体验更佳,勘误也会在博客第一时间更新:
isort井井有条 —— Python导入格式化工具 - muzing的杂货铺
isort your imports, so you don’t have to.
GitHub | 官方文档 | PyPI | 在线试用
isort 是一个实用的 Python 程序/库,用于按照字母表顺序对 imports 进行排序,并自动按类型(标准库/第三方库/自己的模块/……)划分部分。它为各种编辑器提供了命令行程序、Python 库和插件,以快速对所有导入进行排序。需要 Python 3.6 + ,但也支持 Python 2 。
来看官网提供的例子:
# Before isort
from my_lib import Object
import os
from my_lib import Object3
from my_lib import Object2
import sys
from third_party import lib15, lib1, lib2, lib3, lib4, lib5, lib6, lib7, lib8, lib9, lib10, lib11, lib12, lib13, lib14
import sys
from __future__ import absolute_import
from third_party import lib3
print("Hey")
print("yo")
使用 isort 格式化后:
# After isort
from __future__ import absolute_import
import os
import sys
from third_party import (lib1, lib2, lib3, lib4, lib5, lib6, lib7, lib8,
lib9, lib10, lib11, lib12, lib13, lib14, lib15)
from my_lib import Object, Object2, Object3
print("Hey")
print("yo")
import 部分明显清爽、有条理了许多。
安装非常简单,只需:
pip install isort
安装 isort 并支持 requirements.txt :
pip install isort[requirements_deprecated_finder]
带 Pipfile 支持的 isort 安装:
pip install isort[pipfile_deprecated_finder]
支持两种格式的 isort 安装:
pip install isort[requirements_deprecated_finder,pipfile_deprecated_finder]
Tip
如果您希望 isort 作为项目的 linter,则可能需要为每个使用它的项目添加 isort 作为显示开发依赖项。另一方面,如果您是个人开发人员,只是使用 isort 作为个人工具来清理您自己的 commit ,那么全局或用户级别的安装是有意义的。两者都在一台机器上无缝支持。
在特定文件上运行:
isort mypythonfile.py mypythonfile2.py
递归地使用:
isort .
如果开启了 globstar ,则isort .
等价于:
isort **/*.py
仅查看 isort 将做出的变更,但并不应用:
isort mypythonfile.py --diff
以原子方式对项目运行 isort,仅在不引入语法错误的情况下应用更改:
isort --atomic .
(注意:默认情况下这是禁用的,因为它可以防止 isort 针对使用不同版本的 Python 编写的代码运行。)
更多选项可参阅本文命令行选项一节。
import isort
isort.file("pythonfile.py")
或者
import isort
sorted_code = isort.code("import b\nimport a\n")
更多信息可参阅本文 Python API 一节。
在 isort Wiki 可以查看所有 isort 插件。
可以通过「外部工具」的方式将 isort 集成到 PyCharm 中。
在 macOS / Linux 上:
$ which isort
/usr/local/bin/isort # 可能的位置
类似的,在 Windows 上可以使用 where isort
命令查找。
如果是使用 PyCharm 创建的虚拟环境,则直接使用 $PyInterpreterDirectory$/black
作为程序路径。
打开 文件 -> 设置 -> 工具 -> 外部工具
File -> Settings -> Tools -> External Tools
创建工具
$FilePath$
$ProjectFileDir$
如果需要自定义其他选项,写在 $FilePath$
前即可。
在已经打开的代码编辑界面(或项目文件树的某个目录上)鼠标右键,找到 External Tools -> isort,点击即可。
除了外部工具这种方式,还可以通过 File Watchers 插件使用 isort 。
安装插件后,进入 设置 -> 工具 -> File Watchers,点击 + 以添加一个新的 watcher:
$PyInterpreterDirectory$/python
-m isort $FilePath$
$FilePath$
$ProjectFileDir$
PyCharm 中其实已经内置了自动 import 优化工具。类似于使用 Black 替代内置代码格式化工具的做法,使用 isort 的意义很大程度上在于保持统一。这样在团队协作中,即使有的开发者并不使用 PyCahrm 编辑代码,也可以通过相同配置文件的 isort 确保代码导入风格完全相同。
首先确保已经在 VS Code 中安装了 Python 插件。如果没有安装,则在 VS Code 中按下 Ctrl + P
,并输入如下命令:
ext install ms-python.python
或者直接在扩展商店中搜索 Python 并安装。
按下 Ctrl + ,
,打开 VS Code 设置
在「设置」中搜索 python sort imports ,然后设置一下 isort 脚本位置。例如在我的机器上:
$ whereis isort
isort: /usr/local/bin/isort # 这是我机器上的路径,不一定相同
如果不手动设置 isort 路径,Python 插件将使用其内置的 isort ,目前的版本为 isort==4.3.21 ,相比最新的 isort 5.9 还是有些区别的。
如果需要使用 isort 的自定义选项,在第一行那里「添加项」即可。
直接在已经打开的 Python 文件编辑窗口中点击鼠标右键,弹出的菜单中选择「排序 import 语句」即可。
完整的选项列表和说明可参阅官方文档:「Configuration options for isort」
isort 的命令行选项非常多,这里仅列出了 isort --help 返回的帮助文档中的 general options 部分的内容,并尽我所能做了翻译:
general options:
-h, --help 显示此帮助信息并退出
-V, --version 显示当前安装的 isort 版本
--vn, --version-number
返回仅有当前版本数字而没有 logo 的版本信息
-v, --verbose 显示详细输出,例如跳过文件或检查成功
--only-modified, --om
禁用关于未修改文件的详细输出
--dedup-headings 告知 isort 只显示一次相同的自定义 import 标题注释,
即使有多个部分设置了注释组
-q, --quiet 显示更少的输出,仅输出错误信息
-d, --stdout 强制将结果输出至 stdout 标准输出,而不是就地更改
--overwrite-in-place 告知 isort 使用相同的文件句柄就地覆盖重写
与标准方法相比,性能和内存使用情况会有所下降,但可确保所有
文件标志和模式保持不变
--show-config 查看 isort 的确定配置,以及配置选项的来源
--show-files 查看在当前选项下,哪些文件会被 isort 处理
--df, --diff 显示 isort 将对一个文件做出的所有更改的 diff ,而不是就地更改
-c, --check-only, --check
检查文件中是否存在未排序/未格式化的 import 并将它们打印到命令行
而不修改文件。当没有任何变化时返回 0,当文件被重新格式化时返回 1
--ws, --ignore-whitespace
当使用了 --check-only 选项时,告知 isort 忽略空格的差异
--sp SETTINGS_PATH, --settings-path SETTINGS_PATH, --settings-file SETTINGS_PATH, --settings SETTINGS_PATH
显式设置设置路径或文件,而不是根据文件位置自动确定。
--profile PROFILE 用于配置的基本配置文件类型。配置文件包括:
black, django, pycharm, google, open_stack,plone, attrs,
hug, wemake, appnexus。 以及任何共享的配置文件
--old-finders, --magic-placement
使用依赖于环境自省魔术方法的旧的已弃用的查找器逻辑
-j [JOBS], --jobs [JOBS]
要并行处理的文件数
--ac, --atomic 如果生成的文件包含语法错误,则确保不会保存输出
--interactive 告知 isort 以交互方式应用更改
--format-error FORMAT_ERROR
覆盖用于打印错误的格式
--format-success FORMAT_SUCCESS
覆盖用于打印成功的格式
本节翻译自官方文档 「Add Or Remove Imports」
isort 可以很容易地在多个文件中添加导入语句,同时确保它被正确放置。
向所有文件中添加一个 import:
isort -a "from __future__ import print_function" *.py
仅向已有 import 的文件中添加一个 import :
isort -a "from __future__ import print_function" --append-only *.py
isort 还可以轻松地从多个文件中删除导入,而不必关心它的原始格式。
命令行用法:
isort --rm "os.system" *.py
本节翻译自官方文档 「Programmatic Python API Usage」,更多 API 细节参阅API 参考文档
除了强大的命令行界面, isort 还提供了一个完整的 Python API 。
为使用 Python API ,import isort
然后调用所需要的函数。
每个函数都有完整的类型提示,并且接收和返回的都是 Python 内置对象。
主要包括:
isort.code
- 接收一个包含代码的字符串,并在对 import 排序后返回它isort.check_code
- 接收一个包含代码的字符串,如果所有 import 都已经正确排序,则返回 True
,否则返回 False
isort.stream
- 接收一个包含 Python 代码的输入流和一个输出流。向输出流输出已经对 import 进行了排序的代码。isort.check_stream
- 接收一个包含 Python 代码的输出流,如果所有 import 都已经正确排序,则返回 True
,否则返回 False
isort.file
- 接收 Python 源文件的路径,并就地对 import 进行排序isort.check_file
- 接收 Python 源文件的路径,如果所有 import 都已经正确排序,则返回 True
,否则返回 False
isort.place_module
- 将模块的名称作为字符串并返回为其确定的分类isort.place_module_with_reason
- 将模块的名称作为字符串并返回为其确定的分类,并给出确定该分类的原因有关 API 的完整定义,请参阅API 参考文档,或在交互式解释器中尝试 help(isort)
。
本节翻译自官方文档 「Supported Config Files」
isort 支持许多种标准配置格式,允许将自定义选项快速集成到任何项目中。应用配置时,iosrt 会按照下面列出的顺序查找最近的支持的配置文件。您可以通过从命令行设置 --settings-path
来手动指定设置文件或路径。否则,isort 将遍历最多 25 个父目录,直到找到合适的配置文件。注意 isort 将不会离开 git 或 Mercurial 存储库(检查 .git
或 .hg
目录)。一旦找到文件,它就会停止查找。如果传入了 .isort
或文件流,则配置文件的搜索是相对于当前目录完成的,如果传入多个路径,则是相对于传入的第一个路径。isort 永远不会把多个配置文件合并在一起,因为这可能导致混乱。
Tip
您可以随时通过运行
isort . --show-config
来内省 isort 确定的配置设置,以及找出它选择了哪个配置文件。
isort 将查找设置项的首要位置是在专门的 .isort.cfg 文件中。使用这种配置文件的优点是,它是明确用于 isort 的,且遵循易于理解的格式。不利的方面则在于,在您的项目(也许文件层级关系已经因为数个配置文件而有点混乱了)中又多了一个配置文件。
一个来自 isort 项目本身的例子:
[settings]
profile=hug
src_paths=isort,test
isort 将要查找的第二个位置,一个同样明智的保存配置的选择,是 pyproject.toml 文件中。使用这个配置文件的好处在于,它正很快成为所有 Python 工具保存配置的标准位置。这意味着其他开发人员也会知道来这里查看,您的项目根目录将保持整洁。唯一的缺点是您使用的其他工具可能尚不支持这种格式,从而影响了清洁度。
[tool.isort]
profile = "hug"
src_paths = ["isort", "test"]
setup.cfg
可以被认为是 pyproject.toml
的前身。虽然 isort 和更新的工具越来越多地转移到 pyproject.toml,但如果您依赖于许多使用此标准的工具,那么将您的 isort 配置保存在那里也是自然且合适的。
[isort]
profile=hug
src_paths=isort,test
tox 是 Python 社区常用的一种工具,用于指定多个测试环境。因为 isort 验证通常作为测试步骤运行,所以有些人更喜欢将 isort 配置放在 tox.ini 文件中。
[isort]
最后,isort 将查找带有 Python 源文件设置的 .editorconfig
配置。EditorConfig 是一个项目,可以为文本编辑器行为指定一次配置,允许多个命令行工具和文本编辑器选用它。由于 isort 关心许多和文本编辑器相同的设置(如行长度),因此它也会在这些文件中查找。
可选的,您还可以使用 --settings-file
创建具有自定义名称的配置文件,或者直接将 isort 引导至优先级顺序较低的配置文件。这可能很有用,例如,如果您想为 .py 文件设置一个配置,为 .pyx 设置另一个配置——同时将配置文件保留在存储库的根目录中。
Tip
自定义配置文件应该将它们的配置选项放在
[isort]
部分而不是通用的[settings]
部分。这是因为 isort 无法确定其他工具如何使用配置文件。
本节翻译自官方文档 「Action Comments」
可以通过 Python 代码中的注释控制 isort 的行为。
让 isort 跳过整个文件。
例子:
# !/bin/python3
# isort: skip_file
import os
import sys
...
Warning
这应该尽可能合理地放在文件的最上面。由于 isort 使用的是流式架构,它可能在读到该行注释之前就已经完成了一些工作。一般情况下问题不大,但如果从命令行使用
--diff
或任何交互式选项,则可能造成混乱。
如果将其放在与 import 语句同一行中,则 isort 将不会对此 import 进行排序。更具体地说,它会阻止 import 语句被 isort 识别为 import 。因此,这一行将被视为代码并被推到文件导入部分的下方。
例子:
import b
import a # isort: skip <- this will now stay below b
Note
建议尽可能使用
# isort: off
和# isort: on
或isort: split
来替代,这样行为更明确和可预测。
关闭 isort 解析。# isort: off
语句之后的每一行都将保持不变,直到 # isort: on
注释或文件结束。
例子:
import e
import f
# isort: off
import b
import a
重新打开 isort 解析。这仅在文件上文中存在 isort: off
注释时才有意义!这允许您在其他已排序的导入块周围存在未排序的导入块。
例子:
import e
import f
# isort: off
import b
import a
# isort: on
import c
import d
告知 isort 当前排序部分已完成,所有未来的 import 都属于新的排序分组。
例子:
import e
import f
# isort: split
import a
import b
import c
import d
您还可以内联使用它,来防止 import 在其上方或下方交换位置:
import c
import b # isort: split
import a
Tip
isort split 与在
# isort: off
下一行放置# isort: on
的效果完全相同。
告诉 isort 不自动向这个文件添加 import ,即使已经设置了 --add-imports 。
告诉 isort 不要自动添加特定的导入,即使 --add-imports 说明了要添加它。
本节翻译自官方文档 「Custom Sections and Ordering」
isort 提供了许多功能来配置它如何对导入划分「部分」(section),及如何在这些「部分」内对导入排序。您可以使用 sections
选项来改变「部分」间的顺序,从默认值:
FUTURE,STDLIB,THIRDPARTY,FIRSTPARTY,LOCALFOLDER
改为您的喜好(如果已定义,省略一个默认「部分」可能会导致错误):
sections=FUTURE,STDLIB,FIRSTPARTY,THIRDPARTY,LOCALFOLDER
您也可以定义您自己的「部分」划分及其顺序。
例如:
known_django=django
known_pandas=pandas,numpy
sections=FUTURE,STDLIB,DJANGO,THIRDPARTY,PANDAS,FIRSTPARTY,LOCALFOLDER
将使用指定的已知模块创建两个「部分」。
no_lines_before
选项将防止列出的「部分」被空行与上一个「部分」分开。
例如:
sections=FUTURE,STDLIB,THIRDPARTY,FIRSTPARTY,LOCALFOLDER
no_lines_before=LOCALFOLDER
将产生一个结合了 FIRSTPARTY 和 LOCALFOLDER 模块的「部分」。
重要提示:在设置 known
「部分」时,了解由于历史原因不是直接映射的命名非常重要。对于自定义设置,唯一的区别是大小写(known_custom=custom
VS sections=CUSTOM,...
),其他所有引用按如下方式映射:
known_standard_library
: STANDARD_LIBRARY
extra_standard_library
: STANDARD_LIBRARY
# 类似已知标准库,但附加而不是替换known_future_library
: FUTURE
known_first_party
: FIRSTPARTY
known_third_party
: THIRDPARTY
known_local_folder
: LOCALFOLDER
这可能会在 isort 6.0.0+ 中以向后兼容的方式进行更改。
一些项目更倾向于让每个导入「部分」具有独有的标题,以辅助在扫视时快速识别这些「部分」。isort 也可以自动执行此操作。为此,您只需简单地将每一个您想要设置自动注释的「部分」的 import_heading_{section_name}
设置为所需的注释。
举例来说:
import_heading_stdlib=Standard Library
import_heading_firstparty=My Stuff
将会导致输出如下所示:
# Standard Library
import os
import sys
import django.settings
# My Stuff
import myproject.test
isort 还可以轻松按长度对导入进行排序,只需将 length_sort
选项设置为 True
。这将导致以下输出样式:
from evn.util import (
Pool,
Dict,
Options,
Constant,
DecayDict,
UnexpectedCodePath,
)
也可以通过使用 length_sort_
后跟「部分」名称作为配置项,来选择仅对特定节按导入的长度进行排序,例如:
length_sort_stdlib=1
from
导入「部分」默认情况下,isort 将直接导入(import y
)放在 from 导入(from x import y
)的上面:
import b
from a import a # 这将始终出现在下面,因为它是一个 from 导入。
但是,如果您更喜欢严格按照字母顺序排序,您可以将 force sort within sections 设置为 true。结果是:
from a import a # 现在这将出现在顶部,因为在字母表中 a 在 b 之前
import b
您甚至可以使用from first 告知 isort 始终将 from 导入放在顶部,而不是默认放在底部:
from b import b # 如果 from first 被设置为 True,则所有 from 导入将放置在非 from 导入之前
import a
本节翻译自官方文档 「Multi Line Output Modes」
此配置选项定义了当 from imports 超出 line_length 限制时如何换行,共有 12 种可选的设置:
网格
from third_party import (lib1, lib2, lib3,
lib4, lib5, ...)
垂直
from third_party import (lib1,
lib2,
lib3
lib4,
lib5,
...)
悬挂缩进
from third_party import \
lib1, lib2, lib3, \
lib4, lib5, lib6
垂直悬挂缩进
from third_party import (
lib1,
lib2,
lib3,
lib4,
)
悬挂网格
from third_party import (
lib1, lib2, lib3, lib4,
lib5, ...)
分组悬挂网格
from third_party import (
lib1, lib2, lib3, lib4,
lib5, ...
)
与模式 5 相同
from third_party import lib1, lib2, lib3, ... # NOQA
或者,您可以将 force_single_line
设置为 True
(命令行上的 -sl
),然后每个 import 都会出现在自己的行上:
from third_party import lib1
from third_party import lib2
from third_party import lib3
...
括号垂直悬挂缩进
和 模式 3 - 垂直悬挂缩进相同,但最后一行的右括号缩进。
from third_party import (
lib1,
lib2,
lib3,
lib4,
)
from MODULE import 垂直前缀
当行的长度大于长度限制时,以相同的 from MODULE import
前缀开始一个新行。
from third_party import lib1, lib2, lib3
from third_party import lib4, lib5, lib6
带括号的悬挂缩进
与模式 2 - 悬挂缩进相同,但使用括号而不是反斜杠来包裹长行。
from third_party import (
lib1, lib2, lib3,
lib4, lib5, lib6)
反斜杠网格
与模式 0 - 网格相同,但使用反斜杠而不是括号对导入进行分组。
from third_party import lib1, lib2, lib3, \
lib4, lib5
本节翻译自官方文档 「Compatibility with black」
isort 的代码本身就是使用了 Black 来做代码格式化的。其官方文档也高调宣告了两者的亲密关系。
与 Black 的兼容性对于 isort 项目非常重要,并且从版本 5 就开始了。将 isort 和 Black 协同使用所需的一切操作仅为将 isort 配置文件设置为 “black”。
Tip
除了配置文件之外,通常还需要设置 skip_gitignore (默认情况下不为 isort 启用,因为它需要已经安装了 git)和 line_length(因为它通常偏离 Black 的默认值 88)。
对于正式同时使用 isort 和 Black 的项目,我们建议在项目仓库根目录下的配置文件中设置 Black 配置文件。这样,它与用户如何调用 isort(pre-commit、命令行、或者编辑器集成)无关,Black 配置文件都会自动应用。
例如,您的 pyproject.toml 文件看起来会像这样:
[tool.isort]
profile = "black"
multi_line_output = 3
参阅有关支持的配置文件的更多信息。
要在直接从命令行调用 isort 时使用配置文件选项,只需添加 --profile black 选项:isort --profile black
一个 .travis.yml 的例子:
language: python
python:
- "3.6"
- "3.7"
- "3.8"
install:
- pip install -r requirements-dev.txt
- pip install isort black
- pip install coveralls
script:
- pytest my-package
- isort --profile black my-package
- black --check --diff my-package
after_success:
- coveralls
有关更多配置文件的信息,请参阅内置配置文件。
本节翻译自官方文档 「Using isort with pre-commit」
isort 提供对 pre-commit 的官方支持。
为使用 isort 的官方 pre-commit 集成,请添加以下配置:
- repo: https://github.com/pycqa/isort
rev: 5.8.0
hooks:
- id: isort
name: isort (python)
- id: isort
name: isort (cython)
types: [cython]
- id: isort
name: isort (pyi)
types: [pyi]
放在在您项目的 .pre-commit-config.yaml
文件中 repos
部分下面。
旧版本的 isort 使用了大量魔术方法来确定导入位置,在 CI/CD 上运行时很容易中断。为了解决这个问题,创建了一个名为 seed-isort-config
的实用程序。然而自 isort 5 以来,项目已经大大改进了其放置逻辑,并确保了良好的跨平台一致性。如果您的 pre-commit 配置中有一个名为 seed-isort-config
或类似的东西,强烈建议您删除它。这一定会减慢速度,并且可能与 isort 自己的模块放置逻辑发生冲突。
本节翻译自官方文档 「Git Hook」
isort 提供了一个钩子函数,可以集成到你的 Git pre-commit 脚本中,以在 commit 之前检查 Python 代码。
为实现如果存在 isort 错误(严格模式),将导致 commit 失败,请在 .git/hooks/pre-commit
中包含以下内容:
#!/usr/bin/env python
import sys
from isort.hooks import git_hook
sys.exit(git_hook(strict=True, modify=True, lazy=True, settings_file=""))
如果您只想显示警告,但无论如何都允许 commit ,请在不带 strict 参数的情况下调用 git_hook
。如果您想显示警告,但又不想修复代码,请在不带 modify 参数的情况下调用 git_hook
。lazy
参数用于支持倾向于使用 git commit -a
而不是将文件单独添加到索引中的“懒惰”的用户。将其设置为 True
以确保所有跟踪的文件都被正确 isort ,将其忽略或设置为 False
以仅检查添加到索引中的文件。
如果要为钩子使用特定的配置文件,可以将其路径传递给 settings_file 。如果没有特别指定路径,git_hook
将从包含第一个暂存文件的目录开始搜索配置文件,即按照每个 git diff-index
的顺序,然后向上级目录结构搜索,直到找到一个有效的配置文件,或已经检查了 MAX_CONFIG_SEARCH_DEPTH
深度的目录为止。settings_file 参数用于支持将配置文件保存在可能不是其他文件的父目录中的用户。
本节翻译自官方文档 「Github Action」
isort 提供了一个官方 Github Action ,可用作 CI/CD 工作流程的一部分,以确保项目的导入正确排序。该 action 可以在 Github Actions Marketplace 上找到。
python-isort
插件旨在与 checkout
和 setup-python
操作组合运行。默认情况下,它将从被 linted 的存储库的根目录递归运行,如果代码未能正确排序,它将退出并显示错误。
可选项。要使用的 isort
版本。默认为最新版的 isort
。
可选项。要排序的路径列表,相对于您的项目根目录。默认为 .
。
可选项。isort
配置选项传递给 isort
命令行。默认为 --check-only --diff
。
可选项。在运行 isort 之前要安装的 Python 需求文件的路径。如果提供了多个需求文件,它们之间应该用空格隔开。如果需要自定义包安装,则在使用此操作之前应在单独的步骤中安装依赖项。
Tip
在运行 isort 之前安装项目的依赖项很重要,以便正确排序第三方库。
isort
命令行输出
name: Run isort
on:
- push
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-python@v2
with:
python-version: 3.8
- uses: jamescurtin/isort-action@master
with:
requirementsFiles: "requirements.txt requirements-test.txt"
本节翻译自官方文档 「Setuptools integration」
安装后,isort 启用一个 setuptools
命令,用于检查您的项目声明的 Python 文件。
在命令行上运行 python setup.py isort
将检查您的 py_modules
和 packages
中列出的文件。如果发现任何警告,该命令将以错误代码退出:
$ python setup.py isort
此外,为了允许用户无需自己安装 isort 即可使用该命令,请将 isort 添加到 setup()
的 setup_requires 中,如下所示:
setup(
name="project",
packages=["project"],
setup_requires=[
"isort"
]
)
如果你的项目使用了 isort 工具,可以在 README.md 中加入下面一行:
[![Imports: isort](https://img.shields.io/badge/%20imports-isort-%231674b1?style=flat&labelColor=ef8336)](https://pycqa.github.io/isort/)
这样就可以显示一个 shields 图标了
要报告安全漏洞,请使用 Tidelift security contact 。Tidelift 将协调修复和披露。