使用DataFrame.to_sql指定NVARCHAR长度触发UnicodeDecodeError求助
解决pandas to_sql指定NVARCHAR长度时的UnicodeDecodeError问题
昨天用pandas DataFrame的to_sql方法往数据库写数据,大部分文件都正常,但处理某一个文件时触发了编码错误。
报错代码
data.to_sql( name=f'tbl{table_name}' , schema='stage' , con=odbc_ntt.con , if_exists='replace' , index=False, dtype=sqlalchemy.types.NVARCHAR(length=2000) )
报错信息
UnicodeDecodeError: 'charmap' codec can't decode byte 0x90 in position 2: character maps to <undefined>
正常运行的代码
去掉length=2000参数后,代码能正常执行:
data.to_sql( name=f'tbl{table_name}' , schema='stage' , con=odbc_ntt.con , if_exists='replace' , index=False, dtype=sqlalchemy.types.NVARCHAR )
堆栈跟踪
python -m trace --trace Traceback (most recent call last): File "C:\ProgramData\Anaconda3\lib\runpy.py", line 194, in _run_module_as_main return _run_code(code, main_globals, None, File "C:\ProgramData\Anaconda3\lib\runpy.py", line 87, in _run_code exec(code, run_globals) File "C:\ProgramData\Anaconda3\lib\trace.py", line 755, in <module> main() File "C:\ProgramData\Anaconda3\lib\trace.py", line 735, in main code = compile(fp.read(), opts.progname, 'exec') File "C:\ProgramData\Anaconda3\lib\encodings\cp1252.py", line 23, in decode return codecs.charmap_decode(input,self.errors,decoding_table)[0] UnicodeDecodeError: 'charmap' codec can't decode byte 0x90 in position 2: character maps to <undefined>
已尝试操作
- 检查源文件,未发现可见特殊字符
- 尝试强制UTF-8编码读取文件,无效
可行解决思路
明确指定文件读取编码
系统默认编码(比如cp1252)可能无法解码文件中的隐藏字符,读取DataFrame时指定encoding='utf-8'或encoding='latin-1'(latin-1能兼容所有字节,不会触发解码错误):data = pd.read_csv('目标文件路径', encoding='utf-8') # 或者用latin-1兜底 data = pd.read_csv('目标文件路径', encoding='latin-1')清理DataFrame中的不可打印字符
有些控制字符(比如0x90)在编辑器里看不到,遍历字符串列过滤掉不可打印字符:import string printable_chars = set(string.printable) # 处理所有字符串类型列 for col in data.select_dtypes(include=['object']).columns: data[col] = data[col].apply( lambda x: ''.join([c for c in str(x) if c in printable_chars]) if pd.notna(x) else x )逐列指定数据类型
不要全局设置dtype=sqlalchemy.types.NVARCHAR(length=2000),改成针对每一列单独定义类型字典,避免触发底层编码逻辑的异常:from sqlalchemy import types dtype_config = {col: types.NVARCHAR(length=2000) for col in data.columns} data.to_sql( name=f'tbl{table_name}' , schema='stage' , con=odbc_ntt.con , if_exists='replace' , index=False, dtype=dtype_config )调整ODBC连接编码参数
在ODBC连接字符串中添加编码相关参数,比如CharacterSet=UTF-8或Unicode=True(不同数据库驱动参数可能不同,需对应调整),确保连接的编码和数据编码一致。
内容的提问来源于stack exchange,提问作者Doug Coats
相关产品推荐
相关产品推荐

