Reputation: 51
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,
__next__
method and next(x)
the same ? next(x)
for os.popen
's object ?Last but not least, how do next()
and next
method really work ?
Upvotes: 5
Views: 4115
Reputation: 87361
https://docs.python.org/2/library/functions.html#next says about next
:
Retrieve the next item from the iterator by calling its next() method. If default is given, it is returned if the iterator is exhausted, otherwise StopIteration is raised.
The error message:
TypeError: _wrap_close object is not an iterator
indicates that it's not an iterator. Most probably the __iter__
method is missing.
It's strange that you're getting an error, because this works for me in Python 2.x:
>>> next(os.popen('ls'))
'foo.txt\n'
Upvotes: 0
Reputation: 251116
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)
Upvotes: 6