Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

why the returned object of os.popen doesn't support next() call

Python Docs: os.popen:

Open a pipe to or from command. The return value is an open file object connected to the pipe, which can be read or written depending on whether mode is 'r' (default) or 'w'.

I'm able to use the next method X.__next__() / X.next() (2.X) but not the next(x) call,

  • aren't __next__ method and next(x) the same ?
  • why can't we use next(x) for os.popen's object ?

Last but not least, how do next() and next method really work ?

like image 771
vicious_101 Avatar asked Jun 23 '14 09:06

vicious_101


People also ask

What does OS Popen return in Python?

Description. Python method popen() opens a pipe to or from command. The return value is an open file object connected to the pipe, which can be read or written depending on whether mode is 'r' (default) or 'w'.

What does subprocess Popen return?

Popen Function The function should return a pointer to a stream that may be used to read from or write to the pipe while also creating a pipe between the calling application and the executed command. Immediately after starting, the Popen function returns data, and it does not wait for the subprocess to finish.

Is Popen deprecated?

popen() is not recommended. Deprecated since version 2.6: This function is obsolete.

Does subprocess Popen need to be closed?

There the connection is not closed. So you do not need to close most probably. unrelated: you could use stdin=open('test.


1 Answers

Looking at the source code(Python 3.4) it seems the __next__ method is not implemented in_wrap_close class, so the next() call fails because it fails to find the __next__ method on the class. And the explicit __next__ call works because of the overridden __getattr__ method.

Related source code:

def popen(cmd, mode="r", buffering=-1):
    if not isinstance(cmd, str):
        raise TypeError("invalid cmd type (%s, expected string)" % type(cmd))
    if mode not in ("r", "w"):
        raise ValueError("invalid mode %r" % mode)
    if buffering == 0 or buffering is None:
        raise ValueError("popen() does not support unbuffered streams")
    import subprocess, io
    if mode == "r":
        proc = subprocess.Popen(cmd,
                                shell=True,
                                stdout=subprocess.PIPE,
                                bufsize=buffering)
        return _wrap_close(io.TextIOWrapper(proc.stdout), proc)
    else:
        proc = subprocess.Popen(cmd,
                                shell=True,
                                stdin=subprocess.PIPE,
                                bufsize=buffering)
        return _wrap_close(io.TextIOWrapper(proc.stdin), proc)

# Helper for popen() -- a proxy for a file whose close waits for the process
class _wrap_close:
    def __init__(self, stream, proc):
        self._stream = stream
        self._proc = proc
    def close(self):
        self._stream.close()
        returncode = self._proc.wait()
        if returncode == 0:
            return None
        if name == 'nt':
            return returncode
        else:
            return returncode << 8  # Shift left to match old behavior
    def __enter__(self):
        return self
    def __exit__(self, *args):
        self.close()
    def __getattr__(self, name):
        return getattr(self._stream, name)
    def __iter__(self):
        return iter(self._stream)
like image 62
Ashwini Chaudhary Avatar answered Sep 18 '22 18:09

Ashwini Chaudhary