使用psycopg2插入含特殊字符列的PostgreSQL表时遇格式错误
解决psycopg2插入含特殊字符列名DataFrame时的格式错误
问题根源
你遇到的Error: unsupported format character: '{'错误,是因为列名(如Ni[%{wt}])包含{字符,使用str.format()拼接SQL语句时,{会被识别为格式化占位符的起始标记——即便已经给列名加了双引号,format解析时仍会将{wt}视为待替换的占位符,进而触发错误。
最优解决方案:用psycopg2.sql模块安全构建SQL
psycopg2内置的sql模块专门用于处理SQL标识符(表名、列名),能自动转义特殊字符,无需手动添加双引号,同时彻底避免格式化冲突。
步骤1:导入sql模块
from psycopg2 import sql
步骤2:修改插入函数
def insert(conn, df, table, return_field_list): tuples = [tuple(x) for x in df.to_numpy()] # 用sql.Identifier处理表名和列名,自动完成特殊字符转义 table_ident = sql.Identifier(table) cols_ident = [sql.Identifier(col) for col in df.columns] return_fields_ident = [sql.Identifier(f) for f in return_field_list] # 构建安全的SQL语句 query = sql.SQL("INSERT INTO {} ({}) VALUES (%s) RETURNING {}").format( table_ident, sql.SQL(',').join(cols_ident), sql.SQL(',').join(return_fields_ident) ) cursor = conn.cursor() try: extras.execute_values(cursor, query, tuples) conn.commit() return cursor.fetchall() except (Exception, psycopg2.DatabaseError) as error: print("Error: %s" % error) conn.rollback() cursor.close() return None finally: if cursor is not None: cursor.close()
步骤3:移除手动加双引号的代码
sql.Identifier会自动为含特殊字符的列名添加双引号,因此之前的列名重命名操作可以直接删除:
# 删除这行代码 # df.rename(columns = lambda col: f'"{col}"' if col not in ('id', 'name') else col, inplace=True)
备选方案:手动转义格式字符(不推荐)
如果坚持使用str.format(),可以将列名中的{替换为{{,}替换为}},但这种方法容易遗漏字符,安全性远不如官方模块:
df.rename(columns = lambda col: f'"{col.replace("{","{{").replace("}","}}")}"' if col not in ('id', 'name') else col, inplace=True)
内容的提问来源于stack exchange,提问作者kitchenprinzessin
相关产品推荐
相关产品推荐

