标签:格式化 Python 代码 -- Black 使用 black 五彩斑斓
https://muzing.top/posts/a29e4743/#
良好的 Python 代码应有良好的格式规范(不止于遵守 PEP 8 ),使用一个更强大更专业的代码格式化工具,来替代编辑器自带的「格式化代码」功能是有一定必要的,这还可以使团队成员即使在不同编辑器下工作也可以得到完全相同的风格。相比于目前中文社区中较为流行的 autopep8,其实还有一个更好的选择 —— Black。
Life is short, you need Python.
本文采用了较全面介绍的写法,且对相当一部分的官方文档做了摘录翻译,篇幅较长。如果只是想简单快速上手使用工具,直接阅读前面关于安装、使用的几个小节即可(这些小节前面有这样的紫色的标记提醒),跳过其他部分不会有影响。
简介
Black 的 Logo
“Any color you like.”
GItHub | 官方文档 | PyPI | 在线试用
Black 自称“零妥协代码格式化工具(The uncompromising code formatter)”。
截止到 2022 年 11 月,Black 已经在 GitHub 斩获 30.3k 个 Stars,由 Google 开发维护的 YAPF 为 12.9k ,而 autopep8 则只有 4.2k 。可以说 Black 是目前最广受好评的 Python 代码格式化工具。
“Talk is cheap. Show me the code.” 废话不多说,直接看疗效:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
|
# 格式化前 from seven_dwwarfs import Grumpy, Happy, Sleepy, Bashful, Sneezy, Dopey, Doc x = { 'a':37,'b':42,
'c':927}
x = 123456789.123456789E123456789
if very_long_variable_name is not None and \ very_long_variable_name.field > 0 or \ very_long_variable_name.is_debug: z = 'hello '+'world' else: world = 'world' a = 'hello {}'.format(world) f = rf'hello {world}' if (this and that): y = 'hello ''world'#FIXME: https://github.com/psf/black/issues/26 class Foo ( object ): def f (self ): return 37*-2 def g(self, x,y=42): return y def f ( a: List[ int ]) : return 37-a[42-u : y**3] def very_important_function(template: str,*variables,file: os.PathLike,debug:bool=False,): """Applies `variables` to the `template` and writes to `file`.""" with open(file, "w") as f: ... # fmt: off custom_formatting = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, ] # fmt: on regular_formatting = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, ]
PYTHON
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63
|
# 使用 Black-v22.10.0 格式化后 from seven_dwwarfs import Grumpy, Happy, Sleepy, Bashful, Sneezy, Dopey, Doc
x = {"a": 37, "b": 42, "c": 927}
x = 123456789.123456789e123456789
if ( very_long_variable_name is not None and very_long_variable_name.field > 0 or very_long_variable_name.is_debug ): z = "hello " + "world" else: world = "world" a = "hello {}".format(world) f = rf"hello {world}" if this and that: y = "hello " "world" # FIXME: https://github.com/psf/black/issues/26
class Foo(object): def f(self): return 37 * -2
def g(self, x, y=42): return y
def f(a: List[int]): return 37 - a[42 - u : y**3]
def very_important_function( template: str, *variables, file: os.PathLike, debug: bool = False, ): """Applies `variables` to the `template` and writes to `file`.""" with open(file, "w") as f: ...
# fmt: off custom_formatting = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, ] # fmt: on regular_formatting = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, ]
PYTHON
|
经过 Black 重新格式化后,代码立刻就清爽舒适了很多。事实上,Black 有一套经过反复讨论、仔细研究得出的非常详尽的 Python 代码格式化风格,在本文的后面也会展开来讲(见 The Black Code Style 一节)。
安装
本节为快速上手必看
可以通过 pip 直接从 PyPI 下载安装:
1
|
pip install black
SHELL
|
注意需要 Python 3.7 以上的版本。(目前 Python 3.6 已经结束生命周期,3.7 也即将将在2023年6月结束,推荐使用更新版本。)
如果想在 Jupyter Notebooks 中使用,则可以通过如下代码安装:
1
|
pip install black[jupyter]
SHELL
|
如果急于试用最新版本,可以通过下面的命令从 GitHub 安装(不推荐):
1
|
pip install git+git://github.com/psf/black
SHELL
|
简单使用
本节为快速上手必看
作为脚本运行
1
|
black {source_file_or_directory}
SHELL
|
作为 Python 包运行
如果将 Black 作为脚本运行不起作用,您可以尝试将其作为包运行:
1
|
python -m black {source_file_or_directory}
SHELL
|
跳过字符串格式化
Black 会默认将字符串格式化为使用双引号包裹,但有些项目已经使用了单引号的规范且不应修改为双引号,就需要加上一个 -S
/ --skip-string-normalization
的选项。
1
|
black -S {source_file_or_directory}
SHELL
|
其他更多选项
见 详细使用 - 命令行选项 一节
集成到 IDE / 编辑器中
本节为快速上手必看
相比于每次都专门打开一个终端,手动使用命令行调用 Black 格式化代码,我们更希望能把 Black 集成到我们常用的 IDE / 编辑器中,不需要离开写代码的界面即可完成格式化操作。
在 PyCharm 中使用(新版,服务方式)
Black 官方文档中给出了在 PyCharm(或 IntelliJ IDEA)中配置使用 Black 的方法:
-
安装带有额外的 d
的 Black。
1
|
pip install 'black[d]'
SHELL
|
-
安装 BlackConnect IntelliJ IDEs 插件。
-
在 PyCharm/IntelliJ IDEA 中打开插件配置:
在 macOS 上:
PyCharm -> Preferences -> Tools -> BlackConnect
在 Windows / Linux / BSD 上:
File -> Settings -> Tools -> BlackConnect
-
在 Local Instance (shared between projects)
中:
- 勾选
Start local blackd instance when plugin loads
。
- 按下
Path
输入框旁边的 Detect
按钮。插件将会检测到 blackd
可执行文件。
-
在 Trigger Settings
中勾选 Trigger on code reformat
,来启用使用 Black 重新格式化代码。
-
通过选择 Code -> Reformat Code
或使用快捷键格式化当前打开的文件。
-
(可选项)保存文件时自动运行 Black:
- 在插件设置中的
Trigger Settings
中勾选 Trigger when saving changed files
。
BlackConnect 插件设置
在 PyCahrm 中使用(旧版,脚本方式)
Black 官方文档中给出了在 PyCharm(或 IntelliJ IDEA)中配置使用 Black 的方法:
确认 Black 安装位置
在 macOS / Linux / BSD 上:
1 2
|
$ which black /usr/local/bin/black # 可能的位置
SHELL
|
在 Windows 上:
1 2
|
$ where black %LocalAppData%\Programs\Python\Python38\Scripts\black.exe # 可能的位置
POWERSHELL
|
如果是使用 Pycahrm 建立的虚拟环境,则直接使用 $PyInterpreterDirectory$/black
作为程序路径。
在 PyCharm 中添加外部工具
打开 文件 -> 设置 -> 工具 -> 外部工具
File -> Settings -> Tools -> External Tools
打开设置-工具-外部工具
创建工具
- 名称:Black
- 描述:毫不妥协的 Python 代码格式化工具
- 程序:「上一小节得到的安装位置」
- 参数:
$FilePath$
- 工作目录:
$ProjectFileDir$
编辑创建工具
如果需要自定义其他选项,写在 $FilePath$
前即可,比如代表「取消格式化字符串为双引号包裹”」的选项 -S
:
加上其他选项参数
使用
在已经打开的代码编辑界面(或项目文件树的某个目录上)鼠标右键,找到 External Tools -> Black,点击即可。
在右键菜单中使用 Black
设置快捷键
还可以在 设置 -> 键盘映射 -> 外部工具 -> Black 上右键,打开编辑快捷键的菜单,添加键盘快捷键:
设置快捷键
如果已经习惯了 PyCharm 默认的Ctrl + Alt + L
快捷键格式化代码,那么可以这样设置:
- 在 主菜单 -> 代码 -> 重新格式化代码 中删去快捷键
- 给 外部工具 -> External Tools -> Black 设置键盘快捷键
Ctrl + Alt + L
保存文件时自动格式化(可选)
-
确保已经安装了 File Watchers 插件
-
进入 设置 -> 工具 -> File Watchers,点击 + 以添加一个新的 watcher:
- Name: Black
- File type: Python
- Scope: Project Files
- Program: 上一小节得到的安装位置
- Arguments:
$FilePath$
- Output paths to refresh:
$FilePath$
- Working directory:
$ProjectFileDir$
-
在高级选项中:
- 取消勾选 “Auto-save edited files to trigger the watcher”
- 取消勾选 “Trigger the watcher on external changes”
在 VS Code 中使用
VS Code 官方文档介绍
安装 Python 插件
首先确保已经在 VS Code 中安装了 Python 插件。如果没有安装,则在 VS Code 中按下 Ctrl + P
,并输入如下命令:
1
|
ext install ms-python.python
TEXT
|
或者直接在扩展商店中搜索 Python 并安装。
在 VS Code 中安装 Python 插件
配置 Python 扩展
按下 Ctrl + ,
,打开 VS Code 设置
打开 VS Code 设置
在「设置」中搜索 python formatting provider ,然后把默认的 autopep8 改为 black 即可。
更改 Python Formatting Provider
保存文件时自动格式化代码(可选)
在「设置」界面搜索 format on save ,可以勾选打开保存时格式化文件的功能。
保存时自动格式化
取消格式化为双引号包裹字符串(可选)
在「设置」界面的右上角打开 settings.json
配置文件
打开 json 配置文件
在配置文件中添加一行
1 2 3
|
"python.formatting.blackArgs": [ "--skip-string-normalization" ]
JSON
|
添加一行 Black 运行选项
注意每个人的 settings.json
配置文件都有所不同,行号不太一样,在文件末尾新建一行添加即可。
微软官方出品的 Python 扩展体积日渐增长,故微软也在逐渐将其部分功能拆分为单独的扩展。目前 Black Formatter 扩展已经以预发布状态上线 VS Code 插件商店。待该插件转为正式版时,本文会同步更新。
在 Vim 中使用
同样可以在 Black 官方文档中找到在 Vim 中使用 Black 官方插件的方法:https://black.readthedocs.io/en/stable/integrations/editors.html#vim
更多
Black 还可以集成到许多其他编辑器中。此外,官方文档还给出了集成至 GitHub Actions 中、集成至利用 pre-commit 工具实现的版本控制集成工作流中的方法,这样每次更新项目都会自动使用 Black 重新格式化代码了。
详见文档:https://black.readthedocs.io/en/stable/integrations/index.html
详细使用
摘录翻译自官方文档 Usage and Configuration - The basics
Black 是一个工作良好的 Unix 风格命令行工具:
- 当没有原文件传入时什么都不会做
- 如果使用
-
作为文件名,则将会从标准输入读取并写入到标准输出
- 只向用户输出标准错误信息
- 当没有内部错误发生时,退出代码为 0 (除非使用了
--check
选项)
命令行选项
Black 倾向于“独裁”,故意限制并很少添加选项,然而这却反而成了它备受赞赏的一点——既然要统一格式,就不应该有太多个性化选项。
下面列出了 Black 的 Help 输出,并尽我所能做了翻译:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90
|
$ black --help 使用: black [OPTIONS] SRC ...
零妥协的代码格式化工具。
选项: -c, --code TEXT 将传入的代码作为字符串格式化。 -l, --line-length INTEGER 每行允许的字符数。 [默认值: 88]
-t, --target-version [py33|py34|py35|py36|py37|py38|py39|py310|py311] Black 的输出应该支持的 Python 版本 [默认值:每个文件自动检测]
--pyi 不考虑文件扩展名,将所有输入文件格式化为 typing stubs (当使用来自标准输入的管道时很有用)。
--ipynb 不考虑文件扩展名,将所有输入文件格式化为 Jupyter Notebooks 风格(当使用来自标准输入的管道时很有用)。 --python-cell-magics TEXT When processing Jupyter Notebooks, add the given magic to the list of known python- magics (time, capture, pypy, python, prun, timeit, python3). Useful for formatting cells with custom python magics. -x, --skip-source-first-line 跳过源代码的第一行。 -S, --skip-string-normalization 不要标准化字符串引号或前缀。 -C, --skip-magic-trailing-comma 不要将尾随逗号作为分割行的理由。 --preview 启用可能在下一个主要版本中添加到Black的主要功能的 潜在破坏性风格变化。 --check 不要写回文件,只返回状态。 返回代码 0 意味着没有任何改变。 返回代码 1 意味着有些文件将被重新格式化。 返回代码 123 意味着存在 internal error 内部错误。 --diff 不要写回文件, 只是使用 stdout 标准输出显示 每个文件的 diff 差异。 --color / --no-color 显示彩色的 diff。 只有当使用了`--diff` 选项才生效。 --fast / --safe 如果给定了 --fast,则跳过 temporary sanity 检查。 [默认值: --safe] --required-version TEXT 需要运行特定版本的 Black (用于在不同环境上得到同样的 结果,比如使用一个 pyproject.toml 文件)。 --include TEXT 匹配递归搜索中应包含的文件和目录的正则表达式。 空值意味着包含所有文件(无论文件名是什么)。 对所有平台上的目录使用正斜杠(在 Windows 上亦是如此)。 首先匹配要排除的项,然后匹配包含项。 [默认值: (\.pyi?|\.ipynb)$] --exclude TEXT 匹配递归搜索中应排除的文件和目录的正则表达式。 空值意味着不排除任何路径。 对所有平台上的目录使用正斜杠(在 Windows 亦是如此)。 首先匹配要排除的项,然后匹配包含项。 [默认值: /(\.direnv|\.eggs|\.git|\.h g|\.mypy_cache|\.nox|\.tox|\.venv|venv|\.svn |_build|buck-out|build|dist)/] --extend-exclude TEXT 类似 --exclude,但在排除的文件和目录之上 添加了额外的文件和目录。(如果您只是想简单地添加到 默认值,这会很有用) --force-exclude TEXT 类似 --exclude,但是与此正则表达式匹配的文件和目录 将被排除,即使它们作为参数显式传递。 --stdin-filename TEXT 通过 stdin 标准输入传递时的文件名。 有助于确保 Black 在某些依赖使用 stdin 的编辑器上 尊重 --force-exclude 选项。 -W, --workers INTEGER RANGE 并行工作数量 [默认值:系统中的 CPU 数量] [x>=1]。 -q, --quiet 不向 stderr 输出非报错信息。 错误信息仍然会被输出; 使用 2>/dev/null 关闭这些信息。 -v, --verbose 还向 stderr 输出文件未更改或因为排除模式被忽略的信息。 --version 显示版本并退出。 --config FILE 从 FILE 路径读取配置。 -h, --help 显示本帮助信息并退出。
SHELL
|
代码输入选择
从标准输入读取
Black 支持从 stdin 标准输入中读取并格式化代码,并将结果输出至 stdout 标准输出。只需把 -
作为传入路径即可。
1 2 3 4 5
|
$ echo "print ( 'hello, world' )" | black - print("hello, world") reformatted - All done! ✨
标签:格式化,Python,代码,--,Black,使用,black,五彩斑斓
From: https://www.cnblogs.com/sinferwu/p/17082481.html
相关文章
- Python 中global 关键字理解
Python中的global关键字,你了解吗?前言今天来了解下Python中的global关键字。Python变量的作用域实战案例演示之前,先要了解下Python的作用域.Python变量的作...... - python 中给文件加锁——fcntl模块
如果没有fcntl模块则用sudopipinstallfcntl安装模块简单说明:打开文件,不存在则创建之f=open('./test','w')fcntl.flock(f,fcntl.LOCK_EX)这样就对文件t...... - python实现区块链代码
如果你明白了原理其实挺简单的。加密算法是python自带的需要导入hashlibimporthashlibashashsha=hasher.sha256()sha.update('yourcontent')printsha.hexdigest()输...... - Python-接口
fromabcimportABCMeta,abstractmethod#接口:若干抽象方法的集合classPaymet(metaclass=ABCMeta):#abstractmethodclass#抽象方法@abstractmeth...... - Python中报“TypeError: 'int' object is not callable”错误的解决办法
当时就想用sum()函数求和发现之前 “sum” 这个关键字被当变量名定义过了,然后我试着把自己自定义的变量都给删除了,删除之后再次试了一下,发现可以了,果然是sum()函数被之...... - 三行Python代码,让你的数据处理脚本快别人4倍
Python是一门非常适合处理数据和自动化完成重复性工作的编程语言,我们在用数据训练机器学习模型之前,通常都需要对数据进行预处理,而Python就非常适合完成这项工作,比如需要重新...... - Python迭代器,生成器,装饰器
迭代器通常来讲从一个对象中依次取出数据,这个过程叫做遍历,这个手段称为迭代(重复执行某一段代码块,并将每一次迭代得到的结果作为下一次迭代的初始值)。可迭代对象(iterable...... - python生成随机数、随机字符串
importrandomimportstring#随机整数:printrandom.randint(1,50)#随机选取0到100间的偶数:printrandom.randrange(0,101,2)#随机浮点数:printrandom.random()printra...... - 并发编程-Python
目录01、理论多道技术null02、进程进程运行的三状态图同步和异步阻塞和非阻塞开启进程的两种方式进程对象的join方法进程之间数据相互隔离(默认情况下)进程对象及其他方法僵...... - python 大图找小图
frompathlibimportPathimportnumpyimportcv2classImage:def__init__(self,image):self.image=cv2.imread(image,cv2.IMREAD_UNCHANGED)@propert......
|