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

含Unicode特殊字符的Bash输出传入Python触发UnicodeDecodeError求助

报错根因拆解

你遇到的解码报错是两个环节的问题叠加导致的:

  • Shell端的cut -c -65在locale未正确配置UTF-8时,会按字节长度而非字符长度截断字符串。你用到的音乐标题里,日文片假名、「【】」「☯」这类符号都是3字节存储的UTF-8字符,截断到第65字节位置时,刚好把完整的多字节字符从中间切开,生成了不合法的孤立字节(也就是报错里提到的0xe2),这也是单独运行Shell脚本时末尾出现乱码�的原因。
  • Python端读取Shell输出时,默认对解码错误没有容错机制,遇到被截断的非法字节就会直接抛出UnicodeDecodeError,没有做容错替换处理。

修复操作

1. 重构Shell脚本的输出逻辑

彻底去掉Shell端的截断操作,避免切坏多字节字符,修改后的可直接运行脚本:

player_status=$(playerctl status 2> /dev/null)
if [[ $? -eq 0 ]]; then
    metadata="$(playerctl metadata title 2> /dev/null)"
else
    metadata="No music playing"
fi

# 直接输出原始标题,不在Shell层做长度截断
echo "$metadata"

如果一定要在Shell层做截断,需要先在脚本开头加export LC_ALL=C.UTF-8强制启用UTF-8 locale,不然cut依然会按字节切坏多字节字符。

2. 重构Python端的Shell调用逻辑

替换原来的os.popen写法,改成支持指定编码、解码容错的调用方式,同时把截断逻辑移到Python层做,保证多字节字符不会被切坏:

import subprocess

def getMusicName():
    # 调用Shell脚本,关闭默认的严格解码
    shell_run = subprocess.run(
        ["bash", "/home/nep/Self Script/now-playing.sh"],
        capture_output=True,
        encoding="utf-8",
        # 遇到非法截断的字节直接替换为通用替换符,不抛异常
        errors="replace"
    )
    # 去掉输出自带的换行符,再按需截断前65个字符
    return shell_run.stdout.strip()[:65]

修改完成后:

  • 不会再出现因为cut切坏多字节字符导致的编码报错
  • 就算偶尔出现不合法的字节,也会自动替换成可显示的符号,不会中断程序
  • 末尾的自带换行(也就是你看到的⏎标识)会被.strip()自动清掉

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.23 04:45:03