6

Python 2.7 on Ubuntu. I tried run small python script (file converter) for Python3, got error:

$ 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'

I suspect it's caused by syntax differences between python 3 and python 2, here is script itself:

#!/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)

Can anyone advice how to fix this please?

1 Answers1

3

It's an old question, but since I've run into a similar issue and it came up first when googling the error...

Yes, it's caused by a difference between Python 3 and 2. In Python 3, sys.stdin is wrapped in io.TextIOWrapper. In Python 2 it's a file object, which doesn't have a buffer attribute. The same goes for stderr and stdout.

In this case, the same functionality in Python 2 can be achieved using codecs standard library:

ascii_stdin = codecs.getreader("ascii")(sys.stdin, errors="strict")

However, this snippet provides an instance of codecs.StreamReader, not io.TextIOWrapper, so may be not suitable in other cases. And, unfortunately, wrapping Python 2 stdin in io.TextIOWrapper isn't trivial - see Wrap an open stream with io.TextIOWrapper for more discussion on that.

The script in question has more Python 2 incompabilities. Related to the issue in question, sys.stdout doesn't have a buffer attribute, so the last line should be

sys.stdout.write(data)

Other things I can spot:

  • str.split doesn't have maxsplit argument. Use line.split(" ")[:2] instead.
  • int doesn't have a from_bytes attribute. But int(straddr[:-1].encode('hex'), 16) seems to be equivalent.
  • bytes type is Python 3 only. In Python 2, it's an alias for str.
lambdanis
  • 31
  • 5