Search code examples
pythonfileiobackwards-compatibility

Python3 compatability with file object


I have a class/object that is a subprocess of a bunch of cmds in linux. The object has something like:

def __enter__(self):
    self.proc = subprocess.Popen(self.cmd, bufsize=-1, shell=True, stdout=subprocess.PIPE, executable="/bin/bash")
    return self.process.stdout 

This basically return a file object in Python2 and an _io.BufferedReader for Python3.

I perform a bunch of logic on each line and create a bunch of generators. What is the best way to support both python 2 and 3. For example if I have something like

line = input_file.next().strip().split(' ')

Works okay with Python 2, but for Python 3 I'll get something like

`_io.BufferedReader` object has no attribute 'next'

If I update input_file.next() to be input_file.readline() I would get an error of:

a bytes-like object is required, not 'str'

I can keep updating it accordingly to work for Python3, but is there a better way to do it without completely different algo/logic per each case?


Solution

  • The top-level built-in function next works on both Python 2 and Python 3, so instead of input_file.next() use next(input_file). As for consistently splitting on ASCII space characters, just put a b prefix on the string you're using to split; it changes nothing on Python 2 (b' ' is identical to ' ', both being str on Python 2), and on Python 3, it makes it a bytes object (which binary mode Popen processes produce).

    Final version of code is:

    line = next(input_file).strip().split(b' ')
    

    and works identically on both Python 2 and Python 3.