You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用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编码读取文件,无效

可行解决思路

  1. 明确指定文件读取编码
    系统默认编码(比如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')
    
  2. 清理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
        )
    
  3. 逐列指定数据类型
    不要全局设置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
    )
    
  4. 调整ODBC连接编码参数
    在ODBC连接字符串中添加编码相关参数,比如CharacterSet=UTF-8或Unicode=True(不同数据库驱动参数可能不同,需对应调整),确保连接的编码和数据编码一致。

内容的提问来源于stack exchange,提问作者Doug Coats

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.21 20:25:17