修复 AttributeError: 'file' 对象没有属性 'buffer' (Python3)

5 linux type-conversion python-2.7 python-3.x

Ubuntu 上的 Python 2.7。我尝试为 Python3 运行小型 Python 脚本(文件转换器),但出现错误:

$ python uboot_mdb_to_image.py < input.txt > output.bin
Traceback (most recent call last):
  File "uboot_mdb_to_image.py", line 29, in <module>
    ascii_stdin = io.TextIOWrapper(sys.stdin.buffer, encoding='ascii', errors='strict')
AttributeError: 'file' object has no attribute 'buffer'
Run Code Online (Sandbox Code Playgroud)

我怀疑这是由 python 3 和 python 2 之间的语法差异引起的,这里是脚本本身:

#!/usr/bin/env python3

import sys
import io

BYTES_IN_LINE = 0x10 # Number of bytes to expect in each line

c_addr = None
hex_to_ch = {}

ascii_stdin = io.TextIOWrapper(sys.stdin.buffer, encoding='ascii', errors='strict')

for line in ascii_stdin:
    line = line[:-1] # Strip the linefeed (we can't strip all white
                     # space here, think of a line of 0x20s)
    data, ascii_data = line.split("    ", maxsplit = 1)
    straddr, strdata = data.split(maxsplit = 1)
    addr = int.from_bytes(bytes.fromhex(straddr[:-1]), byteorder = 'big')
    if c_addr != addr - BYTES_IN_LINE:
        if c_addr:
            sys.exit("Unexpected c_addr in line: '%s'" % line)
    c_addr = addr
    data = bytes.fromhex(strdata)
    if len(data) != BYTES_IN_LINE:
        sys.exit("Unexpected number of bytes in line: '%s'" % line)
    # Verify that the mapping from hex data to ASCII is consistent (sanity check for transmission errors)
    for b, c in zip(data, ascii_data):
        try:
            if hex_to_ch[b] != c:
                sys.exit("Inconsistency between hex data and ASCII data in line (or the lines before): '%s'" % line)
        except KeyError:
            hex_to_ch[b] = c
    sys.stdout.buffer.write(data)
Run Code Online (Sandbox Code Playgroud)

任何人都可以建议如何解决这个问题吗?

小智 3

这是一个老问题,但由于我遇到了类似的问题,并且在谷歌搜索错误时首先出现......

是的,这是由 Python 3 和 2 之间的差异引起的。在 Python 3 中,sys.stdin被包装在io.TextIOWrapper. 在Python 2 中它是一个file对象,没有属性buffer。stderr和也是如此stdout。

在这种情况下,可以使用codecs标准库实现 Python 2 中的相同功能:

ascii_stdin = codecs.getreader("ascii")(sys.stdin, errors="strict")
Run Code Online (Sandbox Code Playgroud)

codecs.StreamReader但是,此代码片段提供了, not的实例io.TextIOWrapper,因此可能不适合其他情况。而且,不幸的是,包装 Python 2 stdinio.TextIOWrapper并不是一件简单的事 - 请参阅使用 io.TextIOWrapper 包装开放流以获取更多讨论。

相关脚本与 Python 2 存在更多不兼容之处。与所讨论的问题相关,sys.stdout没有buffer属性,所以最后一行应该是

sys.stdout.write(data)
Run Code Online (Sandbox Code Playgroud)

我可以发现的其他事情:

  • str.split没有maxsplit争论。line.split(" ")[:2]代替使用。
  • int没有from_bytes属性。但int(straddr[:-1].encode('hex'), 16)似乎是等价的。
  • bytes类型仅限 Python 3。在 Python 2 中,它是str.