Repository: giampaolo/psutil
Pull request #1481 (2019-04-05 16:49:36)

Cpu freq fix
This PR addresses issue #1472.

`cpu_freq()` is updated to to check whether `/sys/devices/system/cpu/cpufreq/policy*` or `/sys/devices/system/cpu/cpu*/cpufreq` exists.

Tests updated to test for both cases and for multiple CPUs


Patch:
diff --git a/.gitignore b/.gitignore
index 99d0d545..3d22b0b3 100644
--- a/.gitignore
+++ b/.gitignore
@@ -11,6 +11,7 @@ syntax: glob
 *.rej
 *.so
 *.swp
+.failed-tests.txt
 .cache/
 .idea/
 .tox/
diff --git a/psutil/__init__.py b/psutil/__init__.py
index 90066f39..5d2b8d3c 100644
--- a/psutil/__init__.py
+++ b/psutil/__init__.py
@@ -2438,36 +2438,16 @@ if WINDOWS:
 
 
 def test():  # pragma: no cover
-    """List info of all currently running processes emulating ps aux
-    output.
-    """
-    def bytes2human(n):
-        """
-        >>> bytes2human(10000)
-        '9.8 K'
-        >>> bytes2human(100001221)
-        '95.4 M'
-        """
-        symbols = ('K', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y')
-        prefix = {}
-        for i, s in enumerate(symbols):
-            prefix[s] = 1 << (i + 1) * 10
-        for s in reversed(symbols):
-            if n >= prefix[s]:
-                value = float(n) / prefix[s]
-                return '%.1f%s' % (value, s)
-        return '%.1fB' % (n)
+    from ._common import bytes2human
+    from ._compat import get_terminal_size
 
     today_day = datetime.date.today()
-    templ = "%-10s %6s %5s %8s %8s %12s %5s %7s  %s"
-    attrs = ['pid', 'memory_percent', 'name', 'cpu_times', 'create_time',
-             'memory_info']
-    if POSIX:
-        attrs.append('uids')
-        attrs.append('terminal')
-    print(templ % ("USER", "PID", "%MEM", "VSZ", "RSS", "TTY", "START", "TIME",
-                   "COMMAND"))
-    for p in process_iter(attrs=attrs, ad_value=None):
+    templ = "%-10s %5s %5s %7s %7s %5s %6s %6s %6s  %s"
+    attrs = ['pid', 'memory_percent', 'name', 'cmdline', 'cpu_times',
+             'create_time', 'memory_info', 'status', 'nice', 'username']
+    print(templ % ("USER", "PID", "%MEM", "VSZ", "RSS", "NICE",
+                   "STATUS", "START", "TIME", "CMDLINE"))
+    for p in process_iter(attrs, ad_value=None):
         if p.info['create_time']:
             ctime = datetime.datetime.fromtimestamp(p.info['create_time'])
             if ctime.date() == today_day:
@@ -2476,32 +2456,46 @@ def test():  # pragma: no cover
                 ctime = ctime.strftime("%b%d")
         else:
             ctime = ''
-        cputime = time.strftime("%M:%S",
-                                time.localtime(sum(p.info['cpu_times'])))
-        try:
-            user = p.username()[:9]
-        except Error:
-            user = ''
-        if WINDOWS and '\\' in user:
-            user = user.split('\\')[1]
+        if p.info['cpu_times']:
+            cputime = time.strftime("%M:%S",
+                                    time.localtime(sum(p.info['cpu_times'])))
+        else:
+            cputime = ''
 
+        user = p.info['username']
+        if not user and POSIX:
+            try:
+                user = p.uids()[0]
+            except Error:
+                pass
+        if user and WINDOWS and '\\' in user:
+            user = user.split('\\')[1]
+        user = user[:9]
         vms = bytes2human(p.info['memory_info'].vms) if \
             p.info['memory_info'] is not None else ''
         rss = bytes2human(p.info['memory_info'].rss) if \
             p.info['memory_info'] is not None else ''
         memp = round(p.info['memory_percent'], 1) if \
             p.info['memory_percent'] is not None else ''
+        nice = int(p.info['nice']) if p.info['nice'] else ''
+        if p.info['cmdline']:
+            cmdline = ' '.join(p.info['cmdline'])
+        else:
+            cmdline = p.info['name']
+        status = p.info['status'][:5] if p.info['status'] else ''
 
-        print(templ % (
+        line = templ % (
             user[:10],
             p.info['pid'],
             memp,
             vms,
             rss,
-            p.info.get('terminal', '') or '',
+            nice,
+            status,
             ctime,
             cputime,
-            p.info['name'].strip() or '?'))
+            cmdline)
+        print(line[:get_terminal_size()[0]])
 
 
 del memoize, memoize_when_activated, division, deprecated_method
diff --git a/psutil/_common.py b/psutil/_common.py
index 6d430388..0b4f5308 100644
--- a/psutil/_common.py
+++ b/psutil/_common.py
@@ -64,6 +64,7 @@ __all__ = [
     'conn_tmap', 'deprecated_method', 'isfile_strict', 'memoize',
     'parse_environ_block', 'path_exists_strict', 'usage_percent',
     'supports_ipv6', 'sockfam_to_enum', 'socktype_to_enum', "wrap_numbers",
+    'bytes2human',
 ]
 
 
@@ -598,3 +599,23 @@ def open_text(fname, **kwargs):
         kwargs.setdefault('encoding', ENCODING)
         kwargs.setdefault('errors', ENCODING_ERRS)
     return open(fname, "rt", **kwargs)
+
+
+def bytes2human(n, format="%(value).1f%(symbol)s"):
+    """Used by various scripts. See:
+    http://goo.gl/zeJZl
+
+    >>> bytes2human(10000)
+    '9.8K'
+    >>> bytes2human(100001221)
+    '95.4M'
+    """
+    symbols = ('B', 'K', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y')
+    prefix = {}
+    for i, s in enumerate(symbols[1:]):
+        prefix[s] = 1 << (i + 1) * 10
+    for symbol in reversed(symbols[1:]):
+        if n >= prefix[symbol]:
+            value = float(n) / prefix[symbol]
+            return format % locals()
+    return format % dict(symbol=symbols[0], value=n)
diff --git a/psutil/_compat.py b/psutil/_compat.py
index 08aefe4b..c772f61d 100644
--- a/psutil/_compat.py
+++ b/psutil/_compat.py
@@ -10,7 +10,7 @@ import os
 import sys
 
 __all__ = ["PY3", "long", "xrange", "unicode", "basestring", "u", "b",
-           "lru_cache", "which"]
+           "lru_cache", "which", "get_terminal_size"]
 
 PY3 = sys.version_info[0] == 3
 
@@ -239,3 +239,24 @@ except ImportError:
                     if _access_check(name, mode):
                         return name
         return None
+
+
+# python 3.3
+try:
+    from shutil import get_terminal_size
+except ImportError:
+    def get_terminal_size(fallback=(80, 24)):
+        try:
+            import fcntl
+            import termios
+            import struct
+        except ImportError:
+            return fallback
+        else:
+            try:
+                # This should work on Linux.
+                res = struct.unpack(
+                    'hh', fcntl.ioctl(1, termios.TIOCGWINSZ, '1234'))
+                return (res[1], res[0])
+            except Exception:
+                return fallback
diff --git a/psutil/_pslinux.py b/psutil/_pslinux.py
index bf815e87..1f8ddb93 100644
--- a/psutil/_pslinux.py
+++ b/psutil/_pslinux.py
@@ -688,23 +688,19 @@ if os.path.exists("/sys/devices/system/cpu/cpufreq") or \
         Contrarily to other OSes, Linux updates these values in
         real-time.
         """
-        # scaling_* files seem preferable to cpuinfo_*, see:
-        # http://unix.stackexchange.com/a/87537/168884
+        def get_path(num):
+            for p in ("/sys/devices/system/cpu/cpufreq/policy%s" % num,
+                      "/sys/devices/system/cpu/cpu%s/cpufreq" % num):
+                if os.path.exists(p):
+                    return p
+
         ret = []
-        ls = glob.glob("/sys/devices/system/cpu/cpufreq/policy*")
-        if ls:
-            # Sort the list so that '10' comes after '2'. This should
-            # ensure the CPU order is consistent with other CPU functions
-            # having a 'percpu' argument and returning results for multiple
-            # CPUs (cpu_times(), cpu_percent(), cpu_times_percent()).
-            ls.sort(key=lambda x: int(os.path.basename(x)[6:]))
-        else:
-            # https://github.com/giampaolo/psutil/issues/981
-            ls = glob.glob("/sys/devices/system/cpu/cpu[0-9]*/cpufreq")
-            ls.sort(key=lambda x: int(re.search('[0-9]+', x).group(0)))
+        for n in range(cpu_count_logical()):
+            path = get_path(n)
+            if not path:
+                continue
 
-        pjoin = os.path.join
-        for path in ls:
+            pjoin = os.path.join
             curr = cat(pjoin(path, "scaling_cur_freq"), fallback=None)
             if curr is None:
                 # Likely an old RedHat, see:
diff --git a/scripts/cpu_distribution.py b/scripts/cpu_distribution.py
index 67f25b2d..c509c732 100755
--- a/scripts/cpu_distribution.py
+++ b/scripts/cpu_distribution.py
@@ -46,6 +46,7 @@ import sys
 import time
 
 import psutil
+from psutil._compat import get_terminal_size
 
 
 if not hasattr(psutil.Process, "cpu_num"):
@@ -59,24 +60,6 @@ def clean_screen():
         os.system('cls')
 
 
-def get_terminal_size(fallback=(80, 24)):
-    try:
-        # Added in Python 3.3
-        from shutil import get_terminal_size as gts
-        return gts(fallback=fallback)
-    except ImportError:
-        try:
-            # This should work on Linux.
-            import fcntl
-            import termios
-            import struct
-            res = struct.unpack(
-                'hh', fcntl.ioctl(1, termios.TIOCGWINSZ, '1234'))
-            return (res[1], res[0])
-        except Exception:
-            return fallback
-
-
 def main():
     num_cpus = psutil.cpu_count()
     if num_cpus > 8:
diff --git a/scripts/disk_usage.py b/scripts/disk_usage.py
index 37f4da0c..1860401f 100755
--- a/scripts/disk_usage.py
+++ b/scripts/disk_usage.py
@@ -18,23 +18,7 @@ Device               Total     Used     Free  Use %      Type  Mount
 import sys
 import os
 import psutil
-
-
-def bytes2human(n):
-    # http://code.activestate.com/recipes/578019
-    # >>> bytes2human(10000)
-    # '9.8K'
-    # >>> bytes2human(100001221)
-    # '95.4M'
-    symbols = ('K', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y')
-    prefix = {}
-    for i, s in enumerate(symbols):
-        prefix[s] = 1 << (i + 1) * 10
-    for s in reversed(symbols):
-        if n >= prefix[s]:
-            value = float(n) / prefix[s]
-            return '%.1f%s' % (value, s)
-    return "%sB" % n
+from psutil._common import bytes2human
 
 
 def main():
diff --git a/scripts/ifconfig.py b/scripts/ifconfig.py
index e2a9ce53..ad62a44f 100755
--- a/scripts/ifconfig.py
+++ b/scripts/ifconfig.py
@@ -47,6 +47,7 @@ from __future__ import print_function
 import socket
 
 import psutil
+from psutil._common import bytes2human
 
 
 af_map = {
@@ -62,24 +63,6 @@ duplex_map = {
 }
 
 
-def bytes2human(n):
-    """
-    >>> bytes2human(10000)
-    '9.8 K'
-    >>> bytes2human(100001221)
-    '95.4 M'
-    """
-    symbols = ('K', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y')
-    prefix = {}
-    for i, s in enumerate(symbols):
-        prefix[s] = 1 << (i + 1) * 10
-    for s in reversed(symbols):
-        if n >= prefix[s]:
-            value = float(n) / prefix[s]
-            return '%.2f%s' % (value, s)
-    return '%.2fB' % (n)
-
-
 def main():
     stats = psutil.net_if_stats()
     io_counters = psutil.net_io_counters(pernic=True)
diff --git a/scripts/internal/download_exes.py b/scripts/internal/download_exes.py
index 41e303f8..1b72a177 100755
--- a/scripts/internal/download_exes.py
+++ b/scripts/internal/download_exes.py
@@ -21,6 +21,7 @@ import requests
 import shutil
 
 from psutil import __version__ as PSUTIL_VERSION
+from psutil._common import bytes2human
 from scriptutils import printerr, exit
 
 
@@ -50,24 +51,6 @@ def safe_rmtree(path):
     shutil.rmtree(path, onerror=onerror)
 
 
-def bytes2human(n):
-    """
-    >>> bytes2human(10000)
-    '9.8 K'
-    >>> bytes2human(100001221)
-    '95.4 M'
-    """
-    symbols = ('K', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y')
-    prefix = {}
-    for i, s in enumerate(symbols):
-        prefix[s] = 1 << (i + 1) * 10
-    for s in reversed(symbols):
-        if n >= prefix[s]:
-            value = float(n) / prefix[s]
-            return '%.2f %s' % (value, s)
-    return '%.2f B' % (n)
-
-
 def download_file(url):
     local_fname = url.split('/')[-1]
     local_fname = os.path.join('dist', local_fname)
diff --git a/scripts/iotop.py b/scripts/iotop.py
index dabe957b..6a5d3fa9 100755
--- a/scripts/iotop.py
+++ b/scripts/iotop.py
@@ -39,9 +39,9 @@ except ImportError:
     sys.exit('platform not supported')
 
 import psutil
+from psutil._common import bytes2human
 
 
-# --- curses stuff
 def tear_down():
     win.keypad(0)
     curses.nocbreak()
@@ -70,25 +70,6 @@ def print_line(line, highlight=False):
         raise
     else:
         lineno += 1
-# --- /curses stuff
-
-
-def bytes2human(n):
-    """
-    >>> bytes2human(10000)
-    '9.8 K/s'
-    >>> bytes2human(100001221)
-    '95.4 M/s'
-    """
-    symbols = ('K', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y')
-    prefix = {}
-    for i, s in enumerate(symbols):
-        prefix[s] = 1 << (i + 1) * 10
-    for s in reversed(symbols):
-        if n >= prefix[s]:
-            value = float(n) / prefix[s]
-            return '%.2f %s/s' % (value, s)
-    return '%.2f B/s' % (n)
 
 
 def poll(interval):
diff --git a/scripts/meminfo.py b/scripts/meminfo.py
index 88c3a937..0b15ff2b 100755
--- a/scripts/meminfo.py
+++ b/scripts/meminfo.py
@@ -31,23 +31,7 @@ Sout       :      0B
 """
 
 import psutil
-
-
-def bytes2human(n):
-    # http://code.activestate.com/recipes/578019
-    # >>> bytes2human(10000)
-    # '9.8K'
-    # >>> bytes2human(100001221)
-    # '95.4M'
-    symbols = ('K', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y')
-    prefix = {}
-    for i, s in enumerate(symbols):
-        prefix[s] = 1 << (i + 1) * 10
-    for s in reversed(symbols):
-        if n >= prefix[s]:
-            value = float(n) / prefix[s]
-            return '%.1f%s' % (value, s)
-    return "%sB" % n
+from psutil._common import bytes2human
 
 
 def pprint_ntuple(nt):
diff --git a/scripts/nettop.py b/scripts/nettop.py
index e13903c1..45b8879f 100755
--- a/scripts/nettop.py
+++ b/scripts/nettop.py
@@ -40,9 +40,9 @@ except ImportError:
     sys.exit('platform not supported')
 
 import psutil
+from psutil._common import bytes2human
 
 
-# --- curses stuff
 def tear_down():
     win.keypad(0)
     curses.nocbreak()
@@ -71,25 +71,6 @@ def print_line(line, highlight=False):
         raise
     else:
         lineno += 1
-# --- curses stuff
-
-
-def bytes2human(n):
-    """
-    >>> bytes2human(10000)
-    '9.8 K'
-    >>> bytes2human(100001221)
-    '95.4 M'
-    """
-    symbols = ('K', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y')
-    prefix = {}
-    for i, s in enumerate(symbols):
-        prefix[s] = 1 << (i + 1) * 10
-    for s in reversed(symbols):
-        if n >= prefix[s]:
-            value = float(n) / prefix[s]
-            return '%.2f %s' % (value, s)
-    return '%.2f B' % (n)
 
 
 def poll(interval):
diff --git a/scripts/pmap.py b/scripts/pmap.py
index 988b7507..300f23e9 100755
--- a/scripts/pmap.py
+++ b/scripts/pmap.py
@@ -9,7 +9,6 @@ A clone of 'pmap' utility on Linux, 'vmmap' on macOS and 'procstat -v' on BSD.
 Report memory map of a process.
 
 $ python scripts/pmap.py 32402
-pid=32402, name=hg
 Address                 RSS  Mode    Mapping
 0000000000400000      1200K  r-xp    /usr/bin/python2.7
 0000000000838000         4K  r--p    /usr/bin/python2.7
@@ -33,9 +32,12 @@ ffffffffff600000         0K  r-xp    [vsyscall]
 import sys
 
 import psutil
+from psutil._common import bytes2human
+from psutil._compat import get_terminal_size
 
 
 def safe_print(s):
+    s = s[:get_terminal_size()[0]]
     try:
         print(s)
     except UnicodeEncodeError:
@@ -46,19 +48,19 @@ def main():
     if len(sys.argv) != 2:
         sys.exit('usage: pmap <pid>')
     p = psutil.Process(int(sys.argv[1]))
-    print("pid=%s, name=%s" % (p.pid, p.name()))
-    templ = "%-16s %10s  %-7s %s"
+    templ = "%-20s %10s  %-7s %s"
     print(templ % ("Address", "RSS", "Mode", "Mapping"))
     total_rss = 0
     for m in p.memory_maps(grouped=False):
         total_rss += m.rss
         safe_print(templ % (
             m.addr.split('-')[0].zfill(16),
-            str(m.rss / 1024) + 'K',
+            bytes2human(m.rss),
             m.perms,
             m.path))
-    print("-" * 33)
-    print(templ % ("Total", str(total_rss / 1024) + 'K', '', ''))
+    print("-" * 31)
+    print(templ % ("Total", bytes2human(total_rss), '', ''))
+    safe_print("PID = %s, name = %s" % (p.pid, p.name()))
 
 
 if __name__ == '__main__':
diff --git a/scripts/procinfo.py b/scripts/procinfo.py
index 54205de3..161b5057 100755
--- a/scripts/procinfo.py
+++ b/scripts/procinfo.py
@@ -91,6 +91,7 @@ import socket
 import sys
 
 import psutil
+from psutil._common import bytes2human
 
 
 ACCESS_DENIED = ''
@@ -115,18 +116,6 @@ RLIMITS_MAP = {
 }
 
 
-def convert_bytes(n):
-    symbols = ('K', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y')
-    prefix = {}
-    for i, s in enumerate(symbols):
-        prefix[s] = 1 << (i + 1) * 10
-    for s in reversed(symbols):
-        if n >= prefix[s]:
-            value = float(n) / prefix[s]
-            return '%.1f%s' % (value, s)
-    return "%sB" % n
-
-
 def print_(a, b):
     if sys.stdout.isatty() and psutil.POSIX:
         fmt = '\x1b[1;32m%-13s\x1b[0m %s' % (a, b)
@@ -135,13 +124,13 @@ def print_(a, b):
     print(fmt)
 
 
-def str_ntuple(nt, bytes2human=False):
+def str_ntuple(nt, convert_bytes=False):
     if nt == ACCESS_DENIED:
         return ""
-    if not bytes2human:
+    if not convert_bytes:
         return ", ".join(["%s=%s" % (x, getattr(nt, x)) for x in nt._fields])
     else:
-        return ", ".join(["%s=%s" % (x, convert_bytes(getattr(nt, x)))
+        return ", ".join(["%s=%s" % (x, bytes2human(getattr(nt, x)))
                           for x in nt._fields])
 
 
@@ -193,7 +182,7 @@ def run(pid, verbose=False):
     if hasattr(proc, "cpu_num"):
         print_("cpu-num", pinfo["cpu_num"])
 
-    print_('memory', str_ntuple(pinfo['memory_info'], bytes2human=True))
+    print_('memory', str_ntuple(pinfo['memory_info'], convert_bytes=True))
     print_('memory %', round(pinfo['memory_percent'], 2))
     print_('user', pinfo['username'])
     if psutil.POSIX:
@@ -224,7 +213,7 @@ def run(pid, verbose=False):
         print_('num-handles', pinfo['num_handles'])
 
     if 'io_counters' in pinfo:
-        print_('I/O', str_ntuple(pinfo['io_counters'], bytes2human=True))
+        print_('I/O', str_ntuple(pinfo['io_counters'], convert_bytes=True))
     if 'num_ctx_switches' in pinfo:
         print_("ctx-switches", str_ntuple(pinfo['num_ctx_switches']))
     if pinfo['children']:
@@ -322,7 +311,7 @@ def run(pid, verbose=False):
             if not verbose and i >= NON_VERBOSE_ITERATIONS:
                 print_("", "[...]")
                 break
-            print_("", template % (convert_bytes(region.rss), region.path))
+            print_("", template % (bytes2human(region.rss), region.path))
 
 
 def main(argv=None):
diff --git a/scripts/ps.py b/scripts/ps.py
index b85790d6..40dcce20 100755
--- a/scripts/ps.py
+++ b/scripts/ps.py
@@ -5,99 +5,97 @@
 # found in the LICENSE file.
 
 """
-A clone of 'ps -aux' on UNIX.
+A clone of 'ps aux'.
 
 $ python scripts/ps.py
-...
+USER         PID  %MEM     VSZ     RSS  NICE STATUS  START   TIME  CMDLINE
+root           1   0.0  220.9M    6.5M        sleep  Mar27  09:10  /lib/systemd
+root           2   0.0    0.0B    0.0B        sleep  Mar27  00:00  kthreadd
+root           4   0.0    0.0B    0.0B   -20   idle  Mar27  00:00  kworker/0:0H
+root           6   0.0    0.0B    0.0B   -20   idle  Mar27  00:00  mm_percpu_wq
+root           7   0.0    0.0B    0.0B        sleep  Mar27  00:06  ksoftirqd/0
+root           8   0.0    0.0B    0.0B         idle  Mar27  03:32  rcu_sched
+root           9   0.0    0.0B    0.0B         idle  Mar27  00:00  rcu_bh
+root          10   0.0    0.0B    0.0B        sleep  Mar27  00:00  migration/0
+root          11   0.0    0.0B    0.0B        sleep  Mar27  00:00  watchdog/0
+root          12   0.0    0.0B    0.0B        sleep  Mar27  00:00  cpuhp/0
+root          13   0.0    0.0B    0.0B        sleep  Mar27  00:00  cpuhp/1
+root          14   0.0    0.0B    0.0B        sleep  Mar27  00:01  watchdog/1
+root          15   0.0    0.0B    0.0B        sleep  Mar27  00:00  migration/1
+[...]
+giampaolo  19704   1.5    1.9G  235.6M        sleep  17:39  01:11  firefox
+root       20414   0.0    0.0B    0.0B         idle  Apr04  00:00  kworker/4:2
+giampaolo  20952   0.0   10.7M  100.0K        sleep  Mar28  00:00  sh -c /usr
+giampaolo  20953   0.0  269.0M  528.0K        sleep  Mar28  00:00  /usr/lib/
+giampaolo  22150   3.3    2.4G  525.5M        sleep  Apr02  49:09  /usr/lib/
+root       22338   0.0    0.0B    0.0B         idle  02:04  00:00  kworker/1:2
+giampaolo  24123   0.0   35.0M    7.0M        sleep  02:12  00:02  bash
 """
 
 import datetime
-import os
 import time
 
 import psutil
-
-
-PROC_STATUSES_RAW = {
-    psutil.STATUS_RUNNING: "R",
-    psutil.STATUS_SLEEPING: "S",
-    psutil.STATUS_DISK_SLEEP: "D",
-    psutil.STATUS_STOPPED: "T",
-    psutil.STATUS_TRACING_STOP: "t",
-    psutil.STATUS_ZOMBIE: "Z",
-    psutil.STATUS_DEAD: "X",
-    psutil.STATUS_WAKING: "WA",
-    psutil.STATUS_IDLE: "I",
-    psutil.STATUS_LOCKED: "L",
-    psutil.STATUS_WAITING: "W",
-}
-
-if hasattr(psutil, 'STATUS_WAKE_KILL'):
-    PROC_STATUSES_RAW[psutil.STATUS_WAKE_KILL] = "WK"
-
-if hasattr(psutil, 'STATUS_SUSPENDED'):
-    PROC_STATUSES_RAW[psutil.STATUS_SUSPENDED] = "V"
+from psutil._common import bytes2human
+from psutil._compat import get_terminal_size
 
 
 def main():
     today_day = datetime.date.today()
-    templ = "%-10s %5s %4s %4s %7s %7s %-13s %-5s %5s %7s  %s"
-    attrs = ['pid', 'cpu_percent', 'memory_percent', 'name', 'cpu_times',
-             'create_time', 'memory_info', 'status']
-    if os.name == 'posix':
-        attrs.append('uids')
-        attrs.append('terminal')
-    print(templ % ("USER", "PID", "%CPU", "%MEM", "VSZ", "RSS", "TTY",
-                   "STAT", "START", "TIME", "COMMAND"))
-    for p in psutil.process_iter():
-        try:
-            pinfo = p.as_dict(attrs, ad_value='')
-        except psutil.NoSuchProcess:
-            pass
-        else:
-            if pinfo['create_time']:
-                ctime = datetime.datetime.fromtimestamp(pinfo['create_time'])
-                if ctime.date() == today_day:
-                    ctime = ctime.strftime("%H:%M")
-                else:
-                    ctime = ctime.strftime("%b%d")
+    templ = "%-10s %5s %5s %7s %7s %5s %6s %6s %6s  %s"
+    attrs = ['pid', 'memory_percent', 'name', 'cmdline', 'cpu_times',
+             'create_time', 'memory_info', 'status', 'nice', 'username']
+    print(templ % ("USER", "PID", "%MEM", "VSZ", "RSS", "NICE",
+                   "STATUS", "START", "TIME", "CMDLINE"))
+    for p in psutil.process_iter(attrs, ad_value=None):
+        if p.info['create_time']:
+            ctime = datetime.datetime.fromtimestamp(p.info['create_time'])
+            if ctime.date() == today_day:
+                ctime = ctime.strftime("%H:%M")
             else:
-                ctime = ''
+                ctime = ctime.strftime("%b%d")
+        else:
+            ctime = ''
+        if p.info['cpu_times']:
             cputime = time.strftime("%M:%S",
-                                    time.localtime(sum(pinfo['cpu_times'])))
+                                    time.localtime(sum(p.info['cpu_times'])))
+        else:
+            cputime = ''
+
+        user = p.info['username']
+        if not user and psutil.POSIX:
             try:
-                user = p.username()
-            except KeyError:
-                if os.name == 'posix':
-                    if pinfo['uids']:
-                        user = str(pinfo['uids'].real)
-                    else:
-                        user = ''
-                else:
-                    raise
+                user = p.uids()[0]
             except psutil.Error:
-                user = ''
-            if os.name == 'nt' and '\\' in user:
-                user = user.split('\\')[1]
-            vms = pinfo['memory_info'] and \
-                int(pinfo['memory_info'].vms / 1024) or '?'
-            rss = pinfo['memory_info'] and \
-                int(pinfo['memory_info'].rss / 1024) or '?'
-            memp = pinfo['memory_percent'] and \
-                round(pinfo['memory_percent'], 1) or '?'
-            status = PROC_STATUSES_RAW.get(pinfo['status'], pinfo['status'])
-            print(templ % (
-                user[:10],
-                pinfo['pid'],
-                pinfo['cpu_percent'],
-                memp,
-                vms,
-                rss,
-                pinfo.get('terminal', '') or '?',
-                status,
-                ctime,
-                cputime,
-                pinfo['name'].strip() or '?'))
+                pass
+        if user and psutil.WINDOWS and '\\' in user:
+            user = user.split('\\')[1]
+        user = user[:9]
+        vms = bytes2human(p.info['memory_info'].vms) if \
+            p.info['memory_info'] is not None else ''
+        rss = bytes2human(p.info['memory_info'].rss) if \
+            p.info['memory_info'] is not None else ''
+        memp = round(p.info['memory_percent'], 1) if \
+            p.info['memory_percent'] is not None else ''
+        nice = int(p.info['nice']) if p.info['nice'] else ''
+        if p.info['cmdline']:
+            cmdline = ' '.join(p.info['cmdline'])
+        else:
+            cmdline = p.info['name']
+        status = p.info['status'][:5] if p.info['status'] else ''
+
+        line = templ % (
+            user[:10],
+            p.info['pid'],
+            memp,
+            vms,
+            rss,
+            nice,
+            status,
+            ctime,
+            cputime,
+            cmdline)
+        print(line[:get_terminal_size()[0]])
 
 
 if __name__ == '__main__':
diff --git a/scripts/top.py b/scripts/top.py
index 70dbf6c9..16f6da3b 100755
--- a/scripts/top.py
+++ b/scripts/top.py
@@ -10,27 +10,26 @@ A clone of top / htop.
 Author: Giampaolo Rodola' <g.rodola@gmail.com>
 
 $ python scripts/top.py
- CPU0  [|                                       ]   4.9%
- CPU1  [|||                                     ]   7.8%
- CPU2  [                                        ]   2.0%
- CPU3  [|||||                                   ]  13.9%
- Mem   [|||||||||||||||||||                     ]  49.8%  4920M / 9888M
- Swap  [                                        ]   0.0%     0M / 0M
- Processes: 287 (running=1, sleeping=286, zombie=1)
- Load average: 0.34 0.54 0.46  Uptime: 3 days, 10:16:37
-
-PID    USER       NI  VIRT   RES   CPU% MEM%     TIME+  NAME
-------------------------------------------------------------
-989    giampaol    0   66M   12M    7.4  0.1   0:00.61  python
-2083   root        0  506M  159M    6.5  1.6   0:29.26  Xorg
-4503   giampaol    0  599M   25M    6.5  0.3   3:32.60  gnome-terminal
-3868   giampaol    0  358M    8M    2.8  0.1  23:12.60  pulseaudio
-3936   giampaol    0    1G  111M    2.8  1.1  33:41.67  compiz
-4401   giampaol    0  536M  141M    2.8  1.4  35:42.73  skype
-4047   giampaol    0  743M   76M    1.8  0.8  42:03.33  unity-panel-service
-13155  giampaol    0    1G  280M    1.8  2.8  41:57.34  chrome
-10     root        0    0B    0B    0.9  0.0   4:01.81  rcu_sched
-339    giampaol    0    1G  113M    0.9  1.1   8:15.73  chrome
+ CPU0  [||||                                    ]  10.9%
+ CPU1  [|||||                                   ]  13.1%
+ CPU2  [|||||                                   ]  12.8%
+ CPU3  [||||                                    ]  11.5%
+ Mem   [|||||||||||||||||||||||||||||           ]  73.0% 11017M / 15936M
+ Swap  [                                        ]   1.3%   276M / 20467M
+ Processes: 347 (sleeping=273, running=1, idle=73)
+ Load average: 1.10 1.28 1.34  Uptime: 8 days, 21:15:40
+
+PID    USER       NI   VIRT    RES  CPU%  MEM%     TIME+  NAME
+5368   giampaol    0   7.2G   4.3G  41.8  27.7  56:34.18  VirtualBox
+24976  giampaol    0   2.1G 487.2M  18.7   3.1  22:05.16  Web Content
+22731  giampaol    0   3.2G 596.2M  11.6   3.7  35:04.90  firefox
+1202   root        0 807.4M 288.5M  10.6   1.8  12:22.12  Xorg
+22811  giampaol    0   2.8G 741.8M   9.0   4.7   2:26.61  Web Content
+2590   giampaol    0   2.3G 579.4M   5.5   3.6  28:02.70  compiz
+22990  giampaol    0   3.0G   1.2G   4.2   7.6   4:30.32  Web Content
+18412  giampaol    0  90.1M  14.5M   3.5   0.1   0:00.26  python3
+26971  netdata     0  20.8M   3.9M   2.9   0.0   3:17.14  apps.plugin
+2421   giampaol    0   3.3G  36.9M   2.3   0.2  57:14.21  pulseaudio
 ...
 """
 
@@ -45,6 +44,7 @@ except ImportError:
     sys.exit('platform not supported')
 
 import psutil
+from psutil._common import bytes2human
 
 
 # --- curses stuff
@@ -81,24 +81,6 @@ def print_line(line, highlight=False):
 # --- /curses stuff
 
 
-def bytes2human(n):
-    """
-    >>> bytes2human(10000)
-    '9K'
-    >>> bytes2human(100001221)
-    '95M'
-    """
-    symbols = ('K', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y')
-    prefix = {}
-    for i, s in enumerate(symbols):
-        prefix[s] = 1 << (i + 1) * 10
-    for s in reversed(symbols):
-        if n >= prefix[s]:
-            value = int(float(n) / prefix[s])
-            return '%s%s' % (value, s)
-    return "%sB" % n
-
-
 def poll(interval):
     # sleep some time
     time.sleep(interval)
@@ -178,7 +160,7 @@ def print_header(procs_status, num_procs):
 def refresh_window(procs, procs_status):
     """Print results on screen by using curses."""
     curses.endwin()
-    templ = "%-6s %-8s %4s %5s %5s %6s %4s %9s  %2s"
+    templ = "%-6s %-8s %4s %6s %6s %5s %5s %9s  %2s"
     win.erase()
     header = templ % ("PID", "USER", "NI", "VIRT", "RES", "CPU%", "MEM%",
                       "TIME+", "NAME")
diff --git a/scripts/winservices.py b/scripts/winservices.py
index b52aaf21..67724835 100755
--- a/scripts/winservices.py
+++ b/scripts/winservices.py
@@ -27,7 +27,6 @@ binpath: C:\Windows\system32\svchost.exe -k LocalServiceAndNoImpersonation
 Appinfo (Application Information)
 status: stopped, start: manual, username: LocalSystem, pid: None
 binpath: C:\Windows\system32\svchost.exe -k netsvcs
-
 ...
 """
 


Test patch:
diff --git a/psutil/tests/test_linux.py b/psutil/tests/test_linux.py
index 66c50aa6..85cf33c4 100755
--- a/psutil/tests/test_linux.py
+++ b/psutil/tests/test_linux.py
@@ -10,7 +10,6 @@ from __future__ import division
 import collections
 import contextlib
 import errno
-import glob
 import io
 import os
 import re
@@ -698,27 +697,26 @@ class TestSystemCPUFrequency(unittest.TestCase):
 
     @unittest.skipIf(not HAS_CPU_FREQ, "not supported")
     def test_emulate_no_files(self):
-        with mock.patch("psutil._pslinux.glob.glob", return_value=[]):
+        with mock.patch("os.path.exists", return_value=False):
             self.assertIsNone(psutil.cpu_freq())
 
     @unittest.skipIf(TRAVIS, "fails on Travis")
     @unittest.skipIf(not HAS_CPU_FREQ, "not supported")
     def test_emulate_use_second_file(self):
         # https://github.com/giampaolo/psutil/issues/981
-        def glob_mock(pattern):
-            if pattern.startswith("/sys/devices/system/cpu/cpufreq/policy"):
-                flags.append(None)
-                return []
+        def path_exists_mock(path):
+            if path.startswith("/sys/devices/system/cpu/cpufreq/policy"):
+                return False
             else:
                 flags.append(None)
-                return orig_glob(pattern)
+                return orig_exists(path)
 
         flags = []
-        orig_glob = glob.glob
-        with mock.patch("psutil._pslinux.glob.glob", side_effect=glob_mock,
+        orig_exists = os.path.exists
+        with mock.patch("os.path.exists", side_effect=path_exists_mock,
                         create=True):
             assert psutil.cpu_freq()
-            self.assertEqual(len(flags), 2)
+            self.assertEqual(len(flags), psutil.cpu_count(logical=True))
 
     @unittest.skipIf(not HAS_CPU_FREQ, "not supported")
     def test_emulate_use_cpuinfo(self):
@@ -752,11 +750,14 @@ class TestSystemCPUFrequency(unittest.TestCase):
     @unittest.skipIf(not HAS_CPU_FREQ, "not supported")
     def test_emulate_data(self):
         def open_mock(name, *args, **kwargs):
-            if name.endswith('/scaling_cur_freq'):
+            if (name.endswith('/scaling_cur_freq') and
+                    name.startswith("/sys/devices/system/cpu/cpufreq/policy")):
                 return io.BytesIO(b"500000")
-            elif name.endswith('/scaling_min_freq'):
+            elif (name.endswith('/scaling_min_freq') and
+                    name.startswith("/sys/devices/system/cpu/cpufreq/policy")):
                 return io.BytesIO(b"600000")
-            elif name.endswith('/scaling_max_freq'):
+            elif (name.endswith('/scaling_max_freq') and
+                    name.startswith("/sys/devices/system/cpu/cpufreq/policy")):
                 return io.BytesIO(b"700000")
             else:
                 return orig_open(name, *args, **kwargs)
@@ -765,8 +766,7 @@ class TestSystemCPUFrequency(unittest.TestCase):
         patch_point = 'builtins.open' if PY3 else '__builtin__.open'
         with mock.patch(patch_point, side_effect=open_mock):
             with mock.patch(
-                    'glob.glob',
-                    return_value=['/sys/devices/system/cpu/cpufreq/policy0']):
+                    'os.path.exists', return_value=True):
                 freq = psutil.cpu_freq()
                 self.assertEqual(freq.current, 500.0)
                 self.assertEqual(freq.min, 600.0)
@@ -775,26 +775,41 @@ class TestSystemCPUFrequency(unittest.TestCase):
     @unittest.skipIf(not HAS_CPU_FREQ, "not supported")
     def test_emulate_multi_cpu(self):
         def open_mock(name, *args, **kwargs):
-            if name.endswith('/scaling_cur_freq'):
+            n = name
+            if (n.endswith('/scaling_cur_freq') and
+                    n.startswith("/sys/devices/system/cpu/cpufreq/policy0")):
                 return io.BytesIO(b"100000")
-            elif name.endswith('/scaling_min_freq'):
+            elif (n.endswith('/scaling_min_freq') and
+                    n.startswith("/sys/devices/system/cpu/cpufreq/policy0")):
                 return io.BytesIO(b"200000")
-            elif name.endswith('/scaling_max_freq'):
+            elif (n.endswith('/scaling_max_freq') and
+                    n.startswith("/sys/devices/system/cpu/cpufreq/policy0")):
                 return io.BytesIO(b"300000")
+            elif (n.endswith('/scaling_cur_freq') and
+                    n.startswith("/sys/devices/system/cpu/cpufreq/policy1")):
+                return io.BytesIO(b"400000")
+            elif (n.endswith('/scaling_min_freq') and
+                    n.startswith("/sys/devices/system/cpu/cpufreq/policy1")):
+                return io.BytesIO(b"500000")
+            elif (n.endswith('/scaling_max_freq') and
+                    n.startswith("/sys/devices/system/cpu/cpufreq/policy1")):
+                return io.BytesIO(b"600000")
             else:
                 return orig_open(name, *args, **kwargs)
 
         orig_open = open
         patch_point = 'builtins.open' if PY3 else '__builtin__.open'
-        policies = ['/sys/devices/system/cpu/cpufreq/policy0',
-                    '/sys/devices/system/cpu/cpufreq/policy1',
-                    '/sys/devices/system/cpu/cpufreq/policy2']
         with mock.patch(patch_point, side_effect=open_mock):
-            with mock.patch('glob.glob', return_value=policies):
-                freq = psutil.cpu_freq()
-                self.assertEqual(freq.current, 100.0)
-                self.assertEqual(freq.min, 200.0)
-                self.assertEqual(freq.max, 300.0)
+            with mock.patch('os.path.exists', return_value=True):
+                with mock.patch('psutil._pslinux.cpu_count_logical',
+                                return_value=2):
+                    freq = psutil.cpu_freq(percpu=True)
+                    self.assertEqual(freq[0].current, 100.0)
+                    self.assertEqual(freq[0].min, 200.0)
+                    self.assertEqual(freq[0].max, 300.0)
+                    self.assertEqual(freq[1].current, 400.0)
+                    self.assertEqual(freq[1].min, 500.0)
+                    self.assertEqual(freq[1].max, 600.0)
 
     @unittest.skipIf(TRAVIS, "fails on Travis")
     @unittest.skipIf(not HAS_CPU_FREQ, "not supported")
@@ -810,14 +825,12 @@ class TestSystemCPUFrequency(unittest.TestCase):
 
         orig_open = open
         patch_point = 'builtins.open' if PY3 else '__builtin__.open'
-        policies = ['/sys/devices/system/cpu/cpufreq/policy0',
-                    '/sys/devices/system/cpu/cpufreq/policy1',
-                    '/sys/devices/system/cpu/cpufreq/policy2']
-
         with mock.patch(patch_point, side_effect=open_mock):
-            with mock.patch('glob.glob', return_value=policies):
-                freq = psutil.cpu_freq()
-                self.assertEqual(freq.current, 200)
+            with mock.patch('os.path.exists', return_value=True):
+                with mock.patch('psutil._pslinux.cpu_count_logical',
+                                return_value=1):
+                    freq = psutil.cpu_freq()
+                    self.assertEqual(freq.current, 200)
 
         # Also test that NotImplementedError is raised in case no
         # current freq file is present.
@@ -833,7 +846,7 @@ class TestSystemCPUFrequency(unittest.TestCase):
         orig_open = open
         patch_point = 'builtins.open' if PY3 else '__builtin__.open'
         with mock.patch(patch_point, side_effect=open_mock):
-            with mock.patch('glob.glob', return_value=policies):
+            with mock.patch('os.path.exists', return_value=True):
                 self.assertRaises(NotImplementedError, psutil.cpu_freq)
 
 
diff --git a/psutil/tests/test_memory_leaks.py b/psutil/tests/test_memory_leaks.py
index ed3a77fe..170a1d0c 100755
--- a/psutil/tests/test_memory_leaks.py
+++ b/psutil/tests/test_memory_leaks.py
@@ -30,6 +30,7 @@ from psutil import OPENBSD
 from psutil import POSIX
 from psutil import SUNOS
 from psutil import WINDOWS
+from psutil._common import bytes2human
 from psutil._compat import xrange
 from psutil.tests import create_sockets
 from psutil.tests import get_test_subprocess
@@ -73,25 +74,6 @@ def skip_if_linux():
                            "worthless on LINUX (pure python)")
 
 
-def bytes2human(n):
-    """
-    http://code.activestate.com/recipes/578019
-    >>> bytes2human(10000)
-    '9.8K'
-    >>> bytes2human(100001221)
-    '95.4M'
-    """
-    symbols = ('K', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y')
-    prefix = {}
-    for i, s in enumerate(symbols):
-        prefix[s] = 1 << (i + 1) * 10
-    for s in reversed(symbols):
-        if n >= prefix[s]:
-            value = float(n) / prefix[s]
-            return '%.2f%s' % (value, s)
-    return "%sB" % n
-
-
 class TestMemLeak(unittest.TestCase):
     """Base framework class which calls a function many times and
     produces a failure if process memory usage keeps increasing