1

I have a function unzip written in Python2.7

def unzip(text):
    try:
        return gzip.GzipFile(fileobj=StringIO(text)).read()
    except IOError:
        return text

When ran with Python3.7, I'm getting an error

TypeError: can't concat str to bytes

I tried

changing it to return gzip.GzipFile(fileobj=bytes(text, 'utf-8')).read()

But then I got: AttributeError: 'bytes' object has no attribute 'read'

Sebastian Kreft
  • 7,819
  • 3
  • 24
  • 41
Rhs
  • 3,188
  • 12
  • 46
  • 84

1 Answers1

2

StringIO produces string (str) objects and need to be encoded/decoded accordingly. See https://docs.python.org/3/library/io.html#text-i-o.

In your case given that you are dealing with binary data you need to use BytesIO. See https://docs.python.org/3/library/io.html#binary-i-o.

You cannot use bytes directly, as GzipFile expects a file-like object with a read method.

The reason why your code works in python 2 and not in python 3 is because bytes and str are the same in python 2. If you have code that needs to work in both versions, then you may need to use the BytesIO class from the io module. See https://docs.python.org/2.7/library/io.html#binary-i-o.

Sebastian Kreft
  • 7,819
  • 3
  • 24
  • 41
  • 1
    I think you meant (emphasis added): "If you have code that needs to work in both versions, then you may need to use the *BytesIO* class from the `io` module." `GzipFile` expects a binary mode file-like object in both cases; `io.BytesIO` would work in both cases. – ShadowRanger Jul 23 '19 at 21:59
  • Thanks @ShadowRanger I fixed the answer – Sebastian Kreft Jul 23 '19 at 22:04
  • @ShadowRanger Thanks for the insight but in my snippet `text` is a string. Changing to `BytesIO` didn't work since `BytesIO(text)` required that `text` be a byte-like object. – Rhs Jul 25 '19 at 23:31
  • Actually from your post I was able to figure out what was going on. I got it working by doing the following: `return gzip.GzipFile(fileobj=BytesIO(bytes(text, "utf-8"))).read()` – Rhs Jul 25 '19 at 23:38