
本文介绍在利用 Python ast 模块动态生成代码时,如何实现类似人工编写的美观格式(如字典每项独占一行、双引号字符串、正确缩进),并说明为何原生 AST 不支持精细排版,以及推荐的工程化解决方案。
本文介绍在利用 python `ast` 模块动态生成代码时,如何实现类似人工编写的美观格式(如字典每项独占一行、双引号字符串、正确缩进),并说明为何原生 ast 不支持精细排版,以及推荐的工程化解决方案。
Python 的 ast 模块专用于抽象语法树的构建与操作,其核心设计目标是语义正确性与可解析性,而非代码可读性。因此,ast.unparse()(Python 3.9+)仅保证生成合法、等价的源码,但默认采用紧凑单行格式——例如 {'key1': 'value1', 'key2': 'value2'},无法控制换行、缩进或引号风格。
在你的示例中,即使手动设置 lineno 或尝试修改 col_offset,也无法影响 unparse 的格式策略,因为这些字段仅用于错误定位和 AST 遍历,不参与输出渲染逻辑。
✅ 正确解法:将 AST 生成的原始代码交由专业代码格式化工具二次处理。最主流、稳定且符合 PEP 8 的选择是 Black:
import ast
import black
# 构建 AST(保持原逻辑)
my_awesome_properties = [
(ast.Constant(value="key1"), ast.Constant(value="value1")),
(ast.Constant(value="key2"), ast.Constant(value="value2")),
(ast.Constant(value="key3"), ast.Constant(value="value3")),
]
my_awesome_properties_dict = ast.Dict(
keys=[key for key, value in my_awesome_properties],
values=[value for key, value in my_awesome_properties]
)
my_awesome_properties_assignment = ast.Assign(
targets=[ast.Name(id='my_awesome_properties', ctx=ast.Store())],
value=my_awesome_properties_dict
)
my_awesome_module_node = ast.Module(
body=[my_awesome_properties_assignment],
type_ignores=[]
)
# 第一步:生成基础代码
raw_code = ast.unparse(my_awesome_module_node) + "\n" # 确保结尾有换行
# 第二步:用 Black 格式化(自动启用双引号、多行字典、4空格缩进)
formatted_code = black.format_str(
raw_code,
mode=black.FileMode(
line_length=88,
quote_style="double", # 强制双引号(Black 默认优先双引号,此参数在较新版本中为可选)
)
)
print(formatted_code)输出即为:
让 macOS 自动化像说话一样简单 —— 用代码控制你的 Mac,无需学习 AppleScript 系统要求 macOS 14+ (Sonoma) Python 3.9+ 需要开启:辅助功能 + 屏幕录制权限
立即学习“Python免费学习笔记(深入)”;
my_awesome_properties = {
"key1": "value1",
"key2": "value2",
"key3": "value3",
}⚠️ 注意事项:
- 安装 Black:
pip install black -
black.format_str()要求输入为完整、可执行的代码片段(推荐以\n结尾); - 若需严格控制引号,Black 会智能选择(默认倾向双引号),也可通过
--skip-string-normalization等 CLI 参数微调(API 中对应string_normalization=False); - 对于更复杂场景(如嵌套结构、注释注入),可结合
ast.fix_missing_locations()确保位置信息完整,再交由 Black 处理; - 切勿尝试“手动拼接字符串”模拟格式化——这违背 AST 设计初衷,且极易因语法细节(如逗号、括号、换行符位置)导致解析失败。
总结:AST 是代码生成的“骨架”,而 Black 是“美容师”。二者协同,既能保障语法严谨性,又能交付生产级可读代码——这才是现代 Python 元编程的最佳实践。

















