# Buggy code
def as_dict(self, attrs=None, ad_value=None):
    """Utility method returning process information as a
    hashable dictionary.

    If 'attrs' is specified it must be a list of strings
    reflecting available Process class' attribute names
    (e.g. ['cpu_times', 'name']) else all public (read
    only) attributes are assumed.

    'ad_value' is the value which gets assigned in case
    AccessDenied  exception is raised when retrieving that
    particular process information.
    """
    excluded_names = set(
        [
            "send_signal",
            "suspend",
            "resume",
            "terminate",
            "kill",
            "wait",
            "is_running",
            "as_dict",
            "parent",
            "children",
            "rlimit",
        ]
    )
    retdict = dict()
    ls = set(attrs or [x for x in dir(self) if not x.startswith("get")])
    for name in ls:
        if name.startswith("_"):
            continue
        if name.startswith("set_"):
            continue
        if name.startswith("get_"):
            msg = "%s() is deprecated; use %s() instead" % (name, name[4:])
            warnings.warn(msg, category=DeprecationWarning, stacklevel=2)
            name = name[4:]
            if name in ls:
                continue
        if name == "getcwd":
            msg = "getcwd() is deprecated; use cwd() instead"
            warnings.warn(msg, category=DeprecationWarning, stacklevel=2)
            name = "cwd"
            if name in ls:
                continue

        if name in excluded_names:
            continue
        try:
            attr = getattr(self, name)
            if callable(attr):
                ret = attr()
            else:
                ret = attr
        except AccessDenied:
            ret = ad_value
        except NotImplementedError:
            # in case of not implemented functionality (may happen
            # on old or exotic systems) we want to crash only if
            # the user explicitly asked for that particular attr
            if attrs:
                raise
            continue
        retdict[name] = ret
    return retdict


# 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 as_dict(self, attrs=None, ad_value=None):
    """Utility method returning process information as a
    hashable dictionary.

    If 'attrs' is specified it must be a list of strings
    reflecting available Process class' attribute names
    (e.g. ['cpu_times', 'name']) else all public (read
    only) attributes are assumed.

    'ad_value' is the value which gets assigned in case
    AccessDenied or ZombieProcess exception is raised when
    retrieving that particular process information.
    """
    excluded_names = set(
        [
            "send_signal",
            "suspend",
            "resume",
            "terminate",
            "kill",
            "wait",
            "is_running",
            "as_dict",
            "parent",
            "children",
            "rlimit",
        ]
    )
    retdict = dict()
    ls = set(attrs or [x for x in dir(self) if not x.startswith("get")])
    for name in ls:
        if name.startswith("_"):
            continue
        if name.startswith("set_"):
            continue
        if name.startswith("get_"):
            msg = "%s() is deprecated; use %s() instead" % (name, name[4:])
            warnings.warn(msg, category=DeprecationWarning, stacklevel=2)
            name = name[4:]
            if name in ls:
                continue
        if name == "getcwd":
            msg = "getcwd() is deprecated; use cwd() instead"
            warnings.warn(msg, category=DeprecationWarning, stacklevel=2)
            name = "cwd"
            if name in ls:
                continue

        if name in excluded_names:
            continue
        try:
            attr = getattr(self, name)
            if callable(attr):
                ret = attr()
            else:
                ret = attr
        except (AccessDenied, ZombieProcess):
            ret = ad_value
        except NotImplementedError:
            # in case of not implemented functionality (may happen
            # on old or exotic systems) we want to crash only if
            # the user explicitly asked for that particular attr
            if attrs:
                raise
            continue
        retdict[name] = ret
    return retdict