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 Answer 1

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.
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.