Python中查找替换%s、%(named)s格式参数的Pythonic方法是什么
解决方案
Python 标准库没有提供专门处理这类SQL占位符转换的内置函数,也不存在你提到的str.params属性或者通用getparams类工具。你最开始用正则的思路是对的,但是原有实现存在逻辑bug:两次re.sub都基于原始输入字符串操作,第一次替换%s的结果会被第二次替换覆盖,最终%s的修改会失效。
最Pythonic的优化方案是单次正则匹配配合替换回调,一次遍历同时完成占位符替换和参数收集:
import re from typing import Tuple, List, Union def _convert_bindings(query: str) -> Tuple[str, List[Union[None, str]]]: bindings: List[Union[None, str]] = [] # 同时匹配位置占位符%s和命名占位符%(name)s pattern = r"%s|%\((\w+)\)s" def replace_callback(match: re.Match) -> str: named_key = match.group(1) if named_key: # 匹配到命名占位符,收集参数名,替换为@name格式 bindings.append(named_key) return f"@{named_key}" else: # 匹配到位置占位符,收集None标记,替换为?格式 bindings.append(None) return "?" converted_sql = re.sub(pattern, replace_callback, query) return converted_sql, bindings
额外适配说明
如果需要处理SQL语句里的字面量百分号(比如WHERE progress > 90%%这类写法),可以给正则添加负向断言,排除转义的%%场景:
pattern = r"(?<!%)%s|(?<!%)%\((\w+)\)s"
为什么没有内置工具
你提到的str.format是针对{}风格的占位符设计的,和Python %格式化属于两套完全独立的字符串格式化体系,无法直接复用。而你需要的占位符转换属于数据库驱动层的专用逻辑,不同数据库的占位符风格差异很大,因此没有被纳入Python标准库的通用功能中。
内容的提问来源于stack exchange,提问作者Philippe Hebert
相关产品推荐
相关产品推荐

