原生Python下tfds SubwordTextEncoder加载俄乌字符文件报编码错误
问题背景
使用tfds.features.text.SubwordTextEncoder构建包含乌克兰语、俄语字符的词典,词典构建与保存代码如下:
import tensorflow_datasets as tfds text = ['я тут', 'привет', 'вітання'] tokenizer = tfds.features.text.SubwordTextEncoder.build_from_corpus( text, target_vocab_size=2**15) tokenizer.save_to_file('tokenizer.tf')
执行分词器加载代码时触发异常:
tokenizer = tfds.features.text.SubwordTextEncoder.load_from_file('tokenizer.tf')
对应报错信息:
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xd1 in position 81: invalid continuation byte
问题根源为乌克兰语、俄语类UTF-8字符处理逻辑异常,同一段代码在Jupyter Notebook中可正常运行,仅在原生Python环境触发报错。
已尝试无效方案
手动给加载方法传入encoding='utf-8'参数,未解决问题:
tokenizer = tfds.features.text.SubwordTextEncoder.load_from_file('tokenizer.tf', encoding='utf-8')
修复方案
问题本质是旧版本TensorFlow Datasets在原生Python环境下读写分词器文件时,默认调用系统编码而非UTF-8,和Jupyter环境默认强制UTF-8的行为存在差异,导致文件写入阶段西里尔字符就已经损坏,加载时自然解码失败。按以下操作即可修复:
- 保存分词器时,不要直接传文件路径给
save_to_file方法,手动以UTF-8编码打开写入文件句柄传入,从根源避免写入时编码错乱:
import tensorflow_datasets as tfds text = ['я тут', 'привет', 'вітання'] tokenizer = tfds.features.text.SubwordTextEncoder.build_from_corpus( text, target_vocab_size=2**15) # 显式指定UTF-8编码打开写入流 with open('tokenizer.tf', 'w', encoding='utf-8') as f: tokenizer.save_to_file(f)
- 加载分词器时同样手动以UTF-8编码打开读取文件句柄传入,不依赖方法内部的默认文件打开逻辑:
# 显式指定UTF-8编码打开读取流 with open('tokenizer.tf', 'r', encoding='utf-8') as f: tokenizer = tfds.features.text.SubwordTextEncoder.load_from_file(f)
- 之前生成的损坏的分词器文件直接删除,重新执行上述保存逻辑生成新文件即可,不需要调整其他词典构建参数。
该写法兼容所有tfds版本,不受系统默认编码、环境变量差异影响,不会出现Notebook能跑、原生Python跑不通的环境差异问题。如果使用tfds 4.0+版本,升级到最新稳定版也可修复默认编码问题,但显式传入文件句柄的写法兼容性更强。
内容的提问来源于stack exchange,提问作者zer0deck
相关产品推荐
相关产品推荐

