'Python: Bytes Object and Open -- How to create equivalent files?

I have a type bytes file loaded in memory. How can I create identical files, as-if I was loading from my disk with open?

Consider the following:

type(downloaded_bytes)  # bytes
f = io.StringIO(downloaded_bytes.decode('utf-8')).readlines()
f2 = open(r"file.log", "r").readlines()
f == f2  # false

The large thing I noticed inspecting the files is that retrieving the file as bytes has replaced linebreaks. For example, in f2, a line reads like this:

'Initializing error logging... Success\n',

While in the bytes derived file, f, the same line reads:

'Initializing error logging... Success\r\n',

In other areas, \n (the expected line break), is replaced by \r in the bytes file.

How might I force f to be exactly like f2 here?



Solution 1:[1]

If you want to disable line ending translations, while still operating on str, the correct solution is to pass newline='' (or newline="") to open. It still decodes the input to str, and recognizes any form of line separator (\r\n, \n or \r) as a line break, but it doesn't normalize the line separator to a simple \n:

with open(r"file.log", newline='') as f2in:  # Demonstrating with with statement for guarantee close
    f2 = f2in.readlines()

Alternatively, to get rid of the \r in the downloaded bytes rather than preserving it in the file read from disk, the simplest solution is to just perform the line-ending translation yourself (adding import os to top of file if needed to get os.linesep definition):

f = io.StringIO(downloaded_bytes.decode('utf-8').replace(os.linesep, '\n')).readlines()

Solution 2:[2]

You're running on Windows. Which, by convention, uses '\r\n' to terminate lines in "text mode". Open your file in "binary mode" instead:

f2 = open(r"file.log", "rb").readlines()

Note the trailing b in the second argument to open(). Then line-end translations won't happen.

Solution 3:[3]

Well, don't use StringIO for binary stuff, use BytesIO!

from io import BytesIO

f = BytesIO(downloaded_bytes)

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 ShadowRanger
Solution 2 Tim Peters
Solution 3 Sören