Apache Airflow PythonOperator中MySQL查询阿拉伯语字符串乱码问题求助
你遇到的是典型的字符集编码/解码不匹配问题:那种ÙØÙØ¯ اÙÙØ§Ø¬Ø±Ù乱码,本质是UTF-8编码的字节被错误地用Latin-1(ISO-8859-1)解码了。虽然你手动执行了SET语句,但可能连接层面的字符集配置没生效,下面是几个针对性的解决思路:
1. 直接在MySQLHook初始化时指定字符集
Airflow的MySqlHook支持在初始化时传入charset参数,这会在建立连接时直接设置字符集,比手动执行SET语句更可靠。修改你的代码:
source_hook = MySqlHook(mysql_conn_id='mysql_conn', schema='mysql', charset='utf8') # 或者推荐用utf8mb4(支持更完整的Unicode字符,包括emoji等,阿拉伯语也兼容) # source_hook = MySqlHook(mysql_conn_id='mysql_conn', schema='mysql', charset='utf8mb4')
这样就不需要再手动执行SET NAMES等语句了,连接会直接使用指定的字符集。
2. 检查Airflow数据库连接的额外配置
登录Airflow UI,找到你的mysql_conn连接配置,在Extra字段中添加字符集相关参数,确保连接启用Unicode支持:
{"charset": "utf8", "use_unicode": true}
这个配置会覆盖Hook层面的默认设置,确保连接从建立之初就使用正确的字符集。
3. 强制使用支持Unicode的游标
默认的游标可能在处理字符串时存在编码问题,尝试使用字典游标(DictCursor),它会自动处理字符串的编码转换:
from MySQLdb.cursors import DictCursor source_conn = source_hook.get_conn() source_cursor = source_conn.cursor(cursorclass=DictCursor)
这样获取的record中的字符串应该会自动以正确的UTF-8编码返回。
4. 验证连接的字符集状态
如果还是有问题,可以在代码中添加调试语句,查看当前连接的字符集配置,确认是否生效:
source_cursor.execute("SHOW VARIABLES LIKE 'character_set%';") for var in source_cursor.fetchall(): print(f"{var[0]}: {var[1]}")
你需要确保character_set_client、character_set_connection、character_set_results这三个参数的值都是utf8(或utf8mb4),如果不是,说明连接的字符集设置没有生效,需要排查Hook或连接配置的问题。
5. 临时修复:重新编码乱码字符串
如果以上方法都暂时无法生效,可以用编码转换的方式临时修复结果:
test_a = record['name'].encode('latin-1').decode('utf-8') print(test_a)
这是因为当前乱码的字符串是UTF-8字节被错误解码为Latin-1的结果,所以先编码回Latin-1得到原始字节,再解码为UTF-8就能得到正确的阿拉伯语内容。不过这只是临时方案,建议优先从连接层面解决问题。
另外,你的数据表创建语句已经指定了DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci,所以表存储层面的字符集是没问题的,问题主要出在数据读取时的连接字符集配置上。
内容的提问来源于stack exchange,提问作者ResponsibleTrain8

