# Buggy code
def children(self, recursive=False):
    """Return the children of this process as a list of Process
    instances, pre-emptively checking whether PID has been reused.
    If recursive is True return all the parent descendants.

    Example (A == this process):

     A ─┐
        │
        ├─ B (child) ─┐
        │             └─ X (grandchild) ─┐
        │                                └─ Y (great grandchild)
        ├─ C (child)
        └─ D (child)

    >>> import psutil
    >>> p = psutil.Process()
    >>> p.children()
    B, C, D
    >>> p.children(recursive=True)
    B, X, Y, C, D

    Note that in the example above if process X disappears
    process Y won't be listed as the reference to process A
    is lost.
    """
    if hasattr(_psplatform, "ppid_map"):
        # Windows only: obtain a {pid:ppid, ...} dict for all running
        # processes in one shot (faster).
        ppid_map = _psplatform.ppid_map()
    else:
        ppid_map = None

    ret = []
    if not recursive:
        if ppid_map is None:
            # 'slow' version, common to all platforms except Windows
            for p in process_iter():
                try:
                    if p.ppid() == self.pid:
                        # if child happens to be older than its parent
                        # (self) it means child's PID has been reused
                        if self.create_time() <= p.create_time():
                            ret.append(p)
                except NoSuchProcess:
                    pass
        else:
            # Windows only (faster)
            for pid, ppid in ppid_map.items():
                if ppid == self.pid:
                    try:
                        child = Process(pid)
                        # if child happens to be older than its parent
                        # (self) it means child's PID has been reused
                        if self.create_time() <= child.create_time():
                            ret.append(child)
                    except NoSuchProcess:
                        pass
    else:
        # construct a dict where 'values' are all the processes
        # having 'key' as their parent
        table = collections.defaultdict(list)
        if ppid_map is None:
            for p in process_iter():
                try:
                    table[p.ppid()].append(p)
                except NoSuchProcess:
                    pass
        else:
            for pid, ppid in ppid_map.items():
                try:
                    p = Process(pid)
                    table[ppid].append(p)
                except NoSuchProcess:
                    pass
        # At this point we have a mapping table where table[self.pid]
        # are the current process' children.
        # Below, we look for all descendants recursively, similarly
        # to a recursive function call.
        checkpids = [self.pid]
        for pid in checkpids:
            for child in table[pid]:
                try:
                    # if child happens to be older than its parent
                    # (self) it means child's PID has been reused
                    intime = self.create_time() <= child.create_time()
                except NoSuchProcess:
                    pass
                else:
                    if intime:
                        ret.append(child)
                        if child.pid not in checkpids:
                            checkpids.append(child.pid)
    return ret


# Traceback (psutil._error.NoSuchProcess)
How to reproduce:

1. start Photoshop CS6 on a Mountain Lion OSX
2. import psutil; [x.as_dict() for x in psutil.process_iter()] # (in .py file, ipython)



What is the expected output?
A long list of processes and related information



What do you see instead?


$ python test.py
Traceback (most recent call last):
File "test.py", line 3, in <module>
[x.as_dict() for x in psutil.process_iter() if x.is_running()]
File
"/Users/rico/.virtualenvs/temp/lib/python2.7/site-packages/psutil/__init__.py",
line 225, in as_dict
ret = attr()
File
"/Users/rico/.virtualenvs/temp/lib/python2.7/site-packages/psutil/__init__.py",
line 414, in get_nice
return self._platform_impl.get_process_nice()
File
"/Users/rico/.virtualenvs/temp/lib/python2.7/site-packages/psutil/_psosx.py",
line 151, in wrapper
raise NoSuchProcess(self.pid, self._process_name)
psutil._error.NoSuchProcess: process no longer exists (pid=46244)

or within iPython notebook:
[x.as_dict() for x in psutil.process_iter() if x.is_running()]
---------------------------------------------------------------------------
NoSuchProcess                             Traceback (most recent call last)
<ipython-input-108-a71c6dffe397> in <module>()
----> 1 [x.as_dict() for x in psutil.process_iter() if x.is_running()]

/Users/rico/.virtualenvs/temp/lib/python2.7/site-packages/psutil/__init__.pyc
in as_dict(self, attrs, ad_value)
223                         ret = attr(interval=0)
224                     else:
--> 225                         ret = attr()
226                 else:
227                     ret = attr

/Users/rico/.virtualenvs/temp/lib/python2.7/site-packages/psutil/__init__.pyc
in get_nice(self)
412     def get_nice(self):
413         """Get process niceness (priority)."""
--> 414         return self._platform_impl.get_process_nice()
415
416     @_assert_pid_not_reused

/Users/rico/.virtualenvs/temp/lib/python2.7/site-packages/psutil/_psosx.pyc in
wrapper(self, *args, **kwargs)
149             err = sys.exc_info()[1]
150             if err.errno == errno.ESRCH:
--> 151                 raise NoSuchProcess(self.pid, self._process_name)
152             if err.errno in (errno.EPERM, errno.EACCES):
153                 raise AccessDenied(self.pid, self._process_name)

NoSuchProcess: process no longer exists (pid=46243, name='adobe_licutil')

When I close Photoshop, the error will not show up. When starting it again the
error reappears.
An additional is_running() check within the list comprehension does not change
a thing and running the code several times will not change the reported pid.

# Fixed code
def children(self, recursive=False):
    """Return the children of this process as a list of Process
    instances, pre-emptively checking whether PID has been reused.
    If recursive is True return all the parent descendants.

    Example (A == this process):

     A ─┐
        │
        ├─ B (child) ─┐
        │             └─ X (grandchild) ─┐
        │                                └─ Y (great grandchild)
        ├─ C (child)
        └─ D (child)

    >>> import psutil
    >>> p = psutil.Process()
    >>> p.children()
    B, C, D
    >>> p.children(recursive=True)
    B, X, Y, C, D

    Note that in the example above if process X disappears
    process Y won't be listed as the reference to process A
    is lost.
    """
    if hasattr(_psplatform, "ppid_map"):
        # Windows only: obtain a {pid:ppid, ...} dict for all running
        # processes in one shot (faster).
        ppid_map = _psplatform.ppid_map()
    else:
        ppid_map = None

    ret = []
    if not recursive:
        if ppid_map is None:
            # 'slow' version, common to all platforms except Windows
            for p in process_iter():
                try:
                    if p.ppid() == self.pid:
                        # if child happens to be older than its parent
                        # (self) it means child's PID has been reused
                        if self.create_time() <= p.create_time():
                            ret.append(p)
                except (NoSuchProcess, ZombieProcess):
                    pass
        else:
            # Windows only (faster)
            for pid, ppid in ppid_map.items():
                if ppid == self.pid:
                    try:
                        child = Process(pid)
                        # if child happens to be older than its parent
                        # (self) it means child's PID has been reused
                        if self.create_time() <= child.create_time():
                            ret.append(child)
                    except (NoSuchProcess, ZombieProcess):
                        pass
    else:
        # construct a dict where 'values' are all the processes
        # having 'key' as their parent
        table = collections.defaultdict(list)
        if ppid_map is None:
            for p in process_iter():
                try:
                    table[p.ppid()].append(p)
                except (NoSuchProcess, ZombieProcess):
                    pass
        else:
            for pid, ppid in ppid_map.items():
                try:
                    p = Process(pid)
                    table[ppid].append(p)
                except (NoSuchProcess, ZombieProcess):
                    pass
        # At this point we have a mapping table where table[self.pid]
        # are the current process' children.
        # Below, we look for all descendants recursively, similarly
        # to a recursive function call.
        checkpids = [self.pid]
        for pid in checkpids:
            for child in table[pid]:
                try:
                    # if child happens to be older than its parent
                    # (self) it means child's PID has been reused
                    intime = self.create_time() <= child.create_time()
                except (NoSuchProcess, ZombieProcess):
                    pass
                else:
                    if intime:
                        ret.append(child)
                        if child.pid not in checkpids:
                            checkpids.append(child.pid)
    return ret