paramiko-1.16.0 readlines() 解码错误

问题描述 投票:0回答:2

对于来自远程命令的奇怪格式的文本,执行相当标准的 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 decode paramiko readlines
2个回答
2
投票

嗯,我修改了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)

0
投票

基于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
© www.soinside.com 2019 - 2024. All rights reserved.