如何将Python旧式格式化字符串自动转换为f-strings?
你提到的为不同数量%s写多个正则的方式,确实不够通用,遇到复杂场景(比如格式化字符串里本身包含转义的%%、或者元组参数里有嵌套表达式)很容易踩坑。下面给你两种更靠谱的通用解决方案:
方案1:用成熟的自动化工具(推荐)
直接用专门的Python代码升级工具pyupgrade,它能自动识别旧式的%格式化语法,并在合适的场景下转换成f-string,支持任意数量的占位符,还能处理带格式说明符的情况(比如%d、%.2f)。
使用步骤:
- 安装工具:
pip install pyupgrade
- 处理你的代码文件:
pyupgrade --py36-plus your_script.py
这个命令会自动把符合条件的旧式格式化代码转换成f-string,而且能处理各种边缘情况,比自己写正则省心太多。
方案2:基于AST手动实现(适合自定义需求)
如果需要自定义转换逻辑,不要用正则——正则很难处理代码里的嵌套结构和复杂表达式。应该用Python的**抽象语法树(AST)**来解析代码,精准识别旧式格式化节点,再转换成f-string节点。
下面是一个简化版的实现示例:
import ast import astunparse class PercentToFStringTransformer(ast.NodeTransformer): def visit_Call(self, node): # 匹配 print("xxx %s xxx" % (arg1, arg2)) 这类调用结构 if (isinstance(node.func, ast.Name) and node.func.id == 'print' and len(node.args) == 1 and isinstance(node.args[0], ast.BinOp) and isinstance(node.args[0].op, ast.Mod) and isinstance(node.args[0].left, ast.Constant) and isinstance(node.args[0].right, (ast.Tuple, ast.Name, ast.Constant))): format_str = node.args[0].left.value # 处理单个参数的情况(比如 % arg 而不是 %(arg,)) args = node.args[0].right.elts if isinstance(node.args[0].right, ast.Tuple) else [node.args[0].right] # 替换所有%s占位符 parts = [] arg_index = 0 while '%s' in format_str: split_result = format_str.split('%s', 1) parts.append(split_result[0]) # 把参数表达式转成字符串,嵌入f-string arg_code = astunparse.unparse(args[arg_index]).strip() parts.append(f'{{{arg_code}}}') format_str = split_result[1] arg_index += 1 parts.append(format_str) # 构建新的f-string节点 fstring_parts = [] for part in parts: if part.startswith('{') and part.endswith('}'): # 解析表达式节点 expr = ast.parse(part[1:-1]).body[0].value fstring_parts.append(ast.FormattedValue( value=expr, conversion=-1, format_spec=None )) else: fstring_parts.append(ast.Constant(value=part)) node.args[0] = ast.JoinedStr(fstring_parts) return node return self.generic_visit(node) # 测试示例 sample_code = ''' score = 10 total = 20 print("You: %s points. Me: %s points." % (score, total - score)) print("Single value test: %s" % (100,)) print("Escaped percent: %%s is a placeholder" % ("Hello",)) ''' # 解析、转换、输出代码 tree = ast.parse(sample_code) transformer = PercentToFStringTransformer() modified_tree = transformer.visit(tree) print(astunparse.unparse(modified_tree).strip())
这个脚本会把示例中的旧式格式化代码自动转换成f-string,而且能处理单个参数、表达式参数等情况。如果需要支持更多格式说明符(比如%d转成{arg:d}),可以在转换逻辑里扩展判断。
内容的提问来源于stack exchange,提问作者Aristide
相关产品推荐
相关产品推荐

