使用Paramiko列出SFTP文件时出现UnicodeDecodeError求助
解决Paramiko SFTP文件名Unicode解码错误
方案1:替换Paramiko的默认解码函数
Paramiko默认用UTF-8解码文件名,当服务器返回非UTF-8编码的文件名时就会触发解码错误。可以通过Monkey Patch替换它的解码函数,改用Latin-1编码(兼容所有字节,不会抛出解码异常):
import paramiko.util # 自定义解码逻辑,优先尝试UTF-8,失败则用Latin-1兜底 def custom_decode(s, encoding="utf-8"): try: return s.decode(encoding) except UnicodeDecodeError: return s.decode("latin-1") # 替换Paramiko的默认u解码函数 paramiko.util.u = custom_decode
替换后执行原代码,entry.filename就能正常获取文件名。如果明确知道服务器使用的编码(比如GBK、ISO-8859-1),可以把encoding参数改成对应值。
方案2:使用listdir_bytes获取原始字节文件名
直接调用listdir_bytes方法获取字节形式的文件名,自己控制解码逻辑,绕开Paramiko自动解码的问题:
from stat import S_ISREG list_rep = [] path = "/你的目标路径" # 获取字节格式的文件名列表 for filename_bytes in sftp.listdir_bytes(path): # 获取文件属性,需先将字节文件名转成字符串(用Latin-1避免解码报错) file_attr = sftp.stat(f"{path}/{filename_bytes.decode('latin-1')}") # 判断是否为普通文件,且包含目标关键词 if S_ISREG(file_attr.st_mode): filename = filename_bytes.decode('latin-1') if "erapsuspj" in filename: list_rep.append(filename)
这种方法灵活性更高,后续如果需要将文件名转成正确编码,可再做转换(比如filename.encode('latin-1').decode('gbk'),若实际编码为GBK)。
方案3:修改Paramiko源码(不推荐)
如果前两种方案不适用,可直接修改Paramiko库的util.py文件,找到u函数,将默认编码改为latin-1:
def u(s, encoding="latin-1", errors="strict"): return s.decode(encoding, errors=errors)
但该方法会影响所有使用Paramiko的代码,且库升级后修改会丢失,因此优先选择前两种方案。
内容的提问来源于stack exchange,提问作者Alexandre Barrère
相关产品推荐
相关产品推荐

