首页Python【Python计算生态】B...

【Python计算生态】Black——代码格式化工具

Python受欢迎的原因之一就是其计算生态丰富,据不完全统计,Python 目前为止有约13万+的第三方库。

本系列将会陆续整理分享一些有趣、有用的第三方库。

文章配套代码获取有以下两种途径:
  • 通过百度网盘获取:
链接:https://pan.baidu.com/s/1FSGLd7aI_UQlCQuovVHc_Q?pwd=mnsj 提取码:mnsj
  • 前往GitHub获取
https://github.com/returu/Python_Ecosystem





01
简介

Black 是一个强大的 Python 代码格式化工具,旨在自动将 Python 代码格式化为统一的风格,遵循 PEP 8 规范。它的设计理念是“无选择格式化”,即不提供自定义选项,强制执行一套固定的格式化规则。这种设计减少了团队协作中因代码风格不一致而产生的争论,提高了代码的可读性和一致性。许多流行的代码编辑器都支持集成 black,例如,VS CodePyCharmSublimeText等。
关于 Black 代码风格的具体内容可以查看官方文档:
https://black.readthedocs.io/en/stable/the_black_code_style/index.html
直接使用pip安装:
pip install black
如果需要格式化 Jupyter Notebook 文件,需要使用以下命令安装:
pip install "black[jupyter]"
GitHub页面:
https://github.com/psf/black

02
在命令行中使用

  • 1. 格式化文件

使用以下命令 Black 会直接在原地重新格式化文件。

black {source_file_or_directory}
当传递单个脚本文件时,black 会直接修改目标文件,将其格式化为符合其规范的形式。
当传递目录路径时,black 会递归地格式化该目录下的所有 Python 脚本文件。
  • 2命令行选项
运行 black –help 可以显示 Black 的命令行选项,所有命令行选项也可以通过 pyproject.toml 文件配置。
以下是一些常用选项的说明:
  • -l, –line-length
允许的每行字符数。默认值为 88。
  • -t, –target-version
Black 输出应支持的 Python 版本。Black 使用此选项来决定使用哪种语法解析代码。此外,它可能还会根据此选项决定使用哪种风格。例如,函数调用中 *args 后的尾随逗号是在 Python 3.5 中引入的,因此 Black 只有在 Python 3.5 或更高版本时才会添加此逗号。
  • -S, –skip-string-normalization
默认情况下,Black 使用双引号格式化所有字符串,并规范化字符串前缀。如果使用此选项,字符串将保持不变。
  • –check
不写回文件,仅返回状态。Black 将根据以下情况退出:
代码 0:没有任何文件会被更改;
代码 1:某些文件会被重新格式化;
代码 123:发生内部错误。

如果不想直接修改文件,而是想检查代码是否已经符合 black 的格式规范,可以使用 --check 选项。

>>> black --check project_directory/
would reformat F:Black——代码格式化工具project_directoryexample_2.py
would reformat F:Black——代码格式化工具project_directoryexample.py

Oh no! 💥 💔 💥
2 files would be reformatted.
  • –diff
不写回文件,仅输出一个 diff 来指示 Black 会做出哪些更改。它们将被打印到标准输出。如果希望显示彩色 diff,可以使用 –color
>>> black --diff --color project_directory/example_2.py
--- project_directoryexample_2.py      2025-03-08 06:39:49.490746+00:00
+++ project_directoryexample_2.py      2025-03-08 07:53:13.698914+00:00
@@ -1,6 +1,3 @@
-list = [3,
-        4,
-        5
-       ]
-for i,v in enumerate(list):
-    print(f"No.{i} is {v}")
No newline at end of file
+list = [3, 4, 5]
+for i, v in enumerate(list):
+    print(f"No.{i} is {v}")
would reformat project_directoryexample_2.py

All done! ✨ 🍰 ✨
1 file would be reformatted.
  • –line-ranges
指定后,Black 将尽可能只格式化这些行。此选项可以多次指定,格式化的行范围是所有指定范围的并集。每个范围必须以两个整数通过  连接的形式指定:<START>-<END><START> 和 <END> 的整数索引从 1 开始,并且两端都包含。
不过,Black 可能仍然会格式化范围之外的行(例如多行语句)。不支持格式化多个文件或任何 .ipynb 文件时使用此选项。此选项不能在 pyproject.toml 配置文件中指定。
  • –exclude
一个正则表达式,用于匹配在递归搜索中应排除的文件和目录。空值表示不排除任何路径。在所有平台上(包括 Windows),使用正斜杠表示目录。
  • –extend-exclude
与 –exclude 类似,但会在默认值的基础上添加额外的文件和目录,而不是覆盖它们。
  • include
一个正则表达式,用于匹配在递归搜索中应包含的文件和目录。空值表示无论文件名如何,所有文件都将被包含。在所有平台上(包括 Windows),使用正斜杠表示目录。
  • -q, –quiet
停止输出所有非关键信息。错误消息仍将被输出。
  • -v, –verbose
输出未更改或因排除模式而被忽略的文件消息。如果 Black 使用了配置文件,将输出详细的配置文件路径。
使用 --verbose 选项可以显示详细的格式化信息,包括哪些文件被修改等信息。
>>> black --verbose project_directory/
Identified `F:` as project root containing a file system root.
Found input source directory: "F:Black——代码格式化工具project_directory"
reformatted F:Black——代码格式化工具project_directoryexample_2.py
reformatted F:Black——代码格式化工具project_directoryexample.py

All done! ✨ 🍰 ✨
2 files reformatted.
  • 3、pyproject.toml 文件配置
Black 可以从 pyproject.toml 文件(PEP 518将其作为存储 Python 项目构建系统需求的配置文件)中读取命令行选项的项目特定默认值。这对于指定自定义的 –include 和 –exclude / –force-exclude / –extend-exclude 模式特别有用。
pyproject.toml 是一个 TOML 文件。它包含不同工具的独立部分。Black 使用 [tool.black] 部分。选项键与命令行上的长选项名称相同。
默认情况下,Black 会从命令行传递的所有文件和目录的公共基目录开始查找包含 [tool.black] 部分的 pyproject.toml 文件。如果找不到,它会在父目录中查找。通常情况下,pyproject.toml 文件应放在项目的根目录中,与 .git 目录同级。
以下是一个简单的 pyproject.toml 配置示例,用于配置 Black 的格式化行为:
[tool.black]
line-length = 88
target-version = ['py37']
include = '.pyi?$'
# 'extend-exclude' 在默认值的基础上额外排除文件或目录
extend-exclude = '''
# 以 ^/ 开头的正则表达式仅适用于项目根目录中的文件和目录
(
  ^/foo.py    # 排除项目根目录中名为 foo.py 的文件
  | .*_pb2.py  # 排除项目中任何位置的自动生成的 Protocol Buffer 文件
)
'
''

03
在Python脚本中使用

除了在命令行中使用,还可以在 Python 脚本中调用 black 的 API 来格式化代码。

Black 提供了两种主要的 API 方法:
  • black.format_file_contents:
用于格式化字符串形式的代码。
black.format_file_contents(    src_contents: str,     fastbool    mode: black.FileMode) -> str
参数说明:
  • src_contents:需要格式化的代码字符串。
  • fast是否启用快速模式。False(默认)时会执行完整的安全性检查,确保格式化后的代码与原始代码逻辑等价。当为True时跳过代码的安全性检查(AST 检查),可能会更快,但不安全。
  • mode配置格式化的行为。
返回值
格式化后的代码字符串。
异常
black.NothingChanged表示文件已经符合格式化要求,无需更改。black.InvalidInput表示文件中的代码存在语法错误,无法格式化。
以下是一个简单的示例:
import black

source_code = """
def function(x:int,
             y:int
            ):
    result=x ** y
    print(f' Result : { result }')

a=2
b=3
function(a,b)
"
""

# 配置格式化选项
mode = black.Mode(
    line_length=20, # 指定每行代码的最大长度
    string_normalization=False # 是否对字符串进行规范化处理
)

# 格式化代码
formatted_code = black.format_file_contents(source_code, fast=False, mode=mode)
print(formatted_code)
# 输出:格式化后的代码
格式化后的代码:
def function(
    x: int, y: int
):
    result = x**y
    print(
        f' Result : { result }'
    )


a = 2
b = 3
function(a, b)
  • black.format_file_in_place
用于格式化文件路径。
black.format_file_in_place(    src: str,    fastbool,    mode: black.FileMode,    write_back: black.WriteBack) -> bool
参数说明:
  • src:要格式化的文件路径。
  • fast:是否启用快速模式。为False(默认)时会执行完整的安全性检查,确保格式化后的代码与原始代码逻辑等价。当为True时跳过代码的安全性检查(AST 检查),可能会更快,但不安全。
  • mode:配置格式化的行为。
  • write_back控制是否将格式化后的代码写回文件。当设置为black.WriteBack.YES时,会将格式化后的代码写回文件;当设置为black.WriteBack.NO时,不写回文件,仅返回是否需要格式化;当设置为black.WriteBack.DIFF时,生成并返回格式化后的代码与原始代码的差异(diff)。
返回值:
bool类型。如果文件被重新格式化,则返回 True;如果文件无需更改,则返回 False
异常
black.NothingChanged表示文件已经符合格式化要求,无需更改。black.InvalidInput表示文件中的代码存在语法错误,无法格式化。

以下是一个简单的示例:

import black
from pathlib import Path

# 文件路径
file_path = Path("project_directory/example.py")

# 自定义格式化选项
mode = black.Mode(
    line_length=100,  # 设置行长度为 100
    target_versions={black.TargetVersion.PY38},  # 目标 Python 版本
)

# 格式化文件
formatted_code = black.format_file_in_place(file_path, fast=False, mode=mode,write_back=black.WriteBack.YES)
print(formatted_code)
# 输出:True


更多内容可以前往官方文档查看:

https://black.readthedocs.io/en/stable/

本篇文章来源于微信公众号: 码农设计师

RELATED ARTICLES

欢迎留下您的宝贵建议

Please enter your comment!
Please enter your name here

- Advertisment -

Most Popular

Recent Comments