对于来自远程命令的奇怪格式的文本,执行相当标准的 paramiko 实现会在 readlines() 上返回解码错误。我无法更改命令输出。我怎样才能编写代码才能正确解码。请参阅底部的解码错误文本:
正在使用的代码片段:
connect = paramiko.SSHClient()
connect.connect(self.name,
username = self.ruser,
password = password,
key_filename = idkey,
timeout = 15,
)
stdin, stdout, stderr = connect.exec_command(cmd)
retval=stdout.channel.recv_exit_status()
stdin.flush()
stdout.flush()
stderr.flush()
out = stdout.readlines()
sys.exit()
错误文字:
文件“../pylib/hosts/host.py”,第 128 行,在 cmd 中
输出 = stdout.readlines()
文件“/usr/local/lib/python3.4/site-packages/paramiko/file.py”,第 285 行,在 readlines
行= self.readline()
文件“/usr/local/lib/python3.4/site-packages/paramiko/file.py”,第 270 行,在 readline
返回行 if self._flags & self.FLAG_BINARY else u(line)
文件“/usr/local/lib/python3.4/site-packages/paramiko/py3compat.py”,第 148 行,
in u
返回 s.decode(编码)
UnicodeDecodeError:“utf-8”编解码器无法解码位置 80 中的字节 0xe2:无效的连续字节
嗯,我修改了python 3的paramiko.py3compat“u”方法。(没有修改python 2版本)如果utf8解码失败,请尝试ISO-8859-1。标准尝试:除了:包装器。
怀疑此问题仅出现在 Python 3 中。如果能覆盖 py3compay.pt u() 方法而不是修改 paramiko 库文件就好了,但需要继续解决此问题。
这是我修补到 py3compat.py 中的新 u() 方法:
def u(s, encoding='utf8'):
"""cast bytes or unicode to unicode"""
if isinstance(s, bytes):
try:
return s.decode(encoding)
except UnicodeDecodeError:
return s.decode('ISO-8859-1')
elif isinstance(s, str):
return s
else:
raise TypeError("Expected unicode or bytes, got %r" % s)
基于Fragtzack,这里有一个更灵活的方式。
def u(s, encoding="utf8"):
"""cast bytes or unicode to unicode"""
if isinstance(s, bytes):
#return s.decode(encoding)
try:
return s.decode(encoding)
except UnicodeDecodeError:
return decoding(s)
elif isinstance(s, str):
return s
else:
raise TypeError("Expected unicode or bytes, got {!r}".format(s))
def decoding(s, encodings=[ "utf-8", "cp936"]):
"""cast bytes to unicode by encodings"""
for encoding in encodings:
try:
return s.decode(encoding)
except UnicodeDecodeError as lastError:
continue
else:
raise lastError