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

从Amazon Redshift取数据触发UnicodeDecodeError,求助可行方案

解决Redshift stl_querytext字段UTF-8解码错误的可行方案

针对你遇到的stl_querytext.text字段因无效UTF-8字节导致的UnicodeDecodeError,以下是几个可行的解决思路:

1. 在Redshift端将文本转为原始字节,Python端手动处理解码

修改SQL查询,把qt.text转为bytea类型获取原始字节数据,绕过驱动自动解码的限制,在Python中手动指定错误处理策略:

SELECT 
    q.query AS query_id,
    qt.text::bytea AS query_text
FROM 
    pg_catalog.stl_query AS q
INNER JOIN
    pg_catalog.stl_querytext AS qt
    ON q.query = qt.query
WHERE TRUE
    AND DATE(q.starttime) = '2023-10-24'
    AND EXTRACT('hour' FROM q.starttime) = 19

对应的Python代码处理:

from sqlalchemy import create_engine

_QUERY = """
SELECT 
    q.query AS query_id,
    qt.text::bytea AS query_text
FROM 
    pg_catalog.stl_query AS q
INNER JOIN
    pg_catalog.stl_querytext AS qt
    ON q.query = qt.query
WHERE TRUE
    AND DATE(q.starttime) = '2023-10-24'
    AND EXTRACT('hour' FROM q.starttime) = 19
"""

uri = "postgresql+psycopg2://{user}:{password}@{host}:{port}/{database}".format(**_secrets)
engine = create_engine(uri)

with engine.connect() as connection:
    result = connection.execute(_QUERY)
    for row in result:
        query_id = row["query_id"]
        # 手动解码,忽略无效字符或替换为占位符
        query_text = row["query_text"].decode("utf-8", errors="ignore")
        # 或者用errors="replace"把无效字符替换为�
        # query_text = row["query_text"].decode("utf-8", errors="replace")
        print(query_id, query_text)

2. 在Redshift端过滤/修复无效UTF-8字符

利用Redshift内置函数提前处理无效字符:

  • 过滤无效行:使用validate_utf8函数检查文本是否为有效UTF-8,只保留合规行:
SELECT 
    q.query AS query_id,
    qt.text
FROM 
    pg_catalog.stl_query AS q
INNER JOIN
    pg_catalog.stl_querytext AS qt
    ON q.query = qt.query
WHERE TRUE
    AND DATE(q.starttime) = '2023-10-24'
    AND EXTRACT('hour' FROM q.starttime) = 19
    AND validate_utf8(qt.text) IS NOT NULL
  • 修复无效字符:通过编码转换丢弃无效字节,将文本先转成latin1再转回utf-8(会丢失部分特殊字符,但能保留大部分内容):
SELECT 
    q.query AS query_id,
    convert_from(convert_to(qt.text, 'latin1'), 'utf8') AS text
FROM 
    pg_catalog.stl_query AS q
INNER JOIN
    pg_catalog.stl_querytext AS qt
    ON q.query = qt.query
WHERE TRUE
    AND DATE(q.starttime) = '2023-10-24'
    AND EXTRACT('hour' FROM q.starttime) = 19

3. 调整psycopg2客户端编码为latin1,Python端二次转码

在连接URL中指定client_encoding=latin1,先以latin1解码所有数据,再在Python中转成utf-8并处理错误:

uri = "postgresql+psycopg2://{user}:{password}@{host}:{port}/{database}?client_encoding=latin1".format(**_secrets)
engine = create_engine(uri)

with engine.connect() as connection:
    result = connection.execute(_QUERY)
    for row in result:
        query_id = row["query_id"]
        # 先按latin1解码,再转成utf-8并忽略错误
        query_text = row["text"].encode("latin1").decode("utf-8", errors="ignore")
        print(query_id, query_text)

内容的提问来源于stack exchange,提问作者Thomas TYGREAT

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 12:23:17