Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/master' into pslisten
Browse files Browse the repository at this point in the history
* origin/master:
  Fix giampaolo#1276: [AIX] use getargs to get process cmdline (giampaolo#1500) (patch by @wiggin15)
  Fix Process.ionice example using wrong keyword arg (giampaolo#1504)
  fix history syntax
  remove catching IOError; let the test fail and adjust it later
  Fix cpu freq (giampaolo#1496)
  pre release
  fix giampaolo#1493: [Linux] cpu_freq(): handle the case where /sys/devices/system/cpu/cpufreq/ exists but is empty.
  Revert "Fix cpu_freq (giampaolo#1493)" (giampaolo#1495)
  Fix cpu_freq (giampaolo#1493)
  Update cpu_freq to return 0 for max/min if not available (giampaolo#1487)
  give CREDITS to @agnewee for giampaolo#1491
  SunOS / net_if_addrs(): free() ifap struct on error (giampaolo#1491)
  fix giampaolo#1486: add wraps() decorator around wrap_exceptions
  refactor/move some utilities into _common.py
  update doc
  update HISTORY
  Implement getloadavg on Windows. Fixes giampaolo#604 and giampaolo#1484 (giampaolo#1485) (patch by Ammar Askar)
  give credits to @amanusk for giampaolo#1472
  • Loading branch information
nlevitt committed May 6, 2019
2 parents ab4f505 + 7d8c23d commit 68c12ae
Show file tree
Hide file tree
Showing 25 changed files with 408 additions and 108 deletions.
4 changes: 2 additions & 2 deletions .ci/travis/install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ if [[ "$(uname -s)" == 'Darwin' ]]; then
# pyenv virtualenv 2.6.9 psutil
# ;;
py27)
pyenv install 2.7.10
pyenv virtualenv 2.7.10 psutil
pyenv install 2.7.16
pyenv virtualenv 2.7.16 psutil
;;
py36)
pyenv install 3.6.6
Expand Down
14 changes: 12 additions & 2 deletions CREDITS
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,8 @@ I: 517, 607, 610, 1131, 1123, 1130, 1154, 1164, 1174, 1177, 1210, 1214, 1408,

N: Alex Manuskin
W: https://github.com/amanusk
D: FreeBSD cpu_freq(), OSX temperatures, support for Linux temperatures
I: 1284, 1345, 1350, 1352
D: FreeBSD cpu_freq(), OSX temperatures, support for Linux temperatures.
I: 1284, 1345, 1350, 1352, 1472, 1481, 1487.

N: Jeff Tang
W: https://github.com/mrjefftang
Expand Down Expand Up @@ -607,3 +607,13 @@ I: 1471
N: Samer Masterson
W: https://github.com/samertm
I: 1480

N: Ammar Askar
E: ammar@ammaraskar.com
W: http://ammaraskar.com/
I: 604, 1484

N: agnewee
W: https://github.com/Agnewee
C: China
I: 1491
23 changes: 18 additions & 5 deletions HISTORY.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3,35 +3,48 @@
5.6.2
=====

2019-04-26

**Enhancements**

- 604_: [Windows, Windows] add new psutil.getloadavg(), returning system load
average calculation, including on Windows (emulated). (patch by Ammar Askar)
- 1404_: [Linux] cpu_count(logical=False) uses a second method (read from
`/sys/devices/system/cpu/cpu[0-9]/topology/core_id`) in order to determine
the number of physical CPUs in case /proc/cpuinfo does not provide this info.
- 1458_: provide coloured test output. Also show failures on KeyboardInterrupt.
- 1464_: various docfixes (always point to python3 doc, fix links, etc.).
- 1473_: [Windows] process IO priority (ionice()) values are now exposed as 4
new constants: IOPRIO_VERYLOW, IOPRIO_LOW, IOPRIO_NORMAL, IOPRIO_HIGH.
Also it was not possible to set high I/O priority (not it is).
- 1476_: [Windows] it is now possible to set process high I/O priority
(ionice()).Also, I/O priority values are now exposed as 4 new constants:
IOPRIO_VERYLOW, IOPRIO_LOW, IOPRIO_NORMAL, IOPRIO_HIGH.
- 1478_: add make command to re-run tests failed on last run.

**Bug fixes**

- 1223_: [Windows] boot_time() may return value on Windows XP.
- 1462_: [Linux] (tests) make tests invariant to LANG setting (patch by
- 1463_: cpu_distribution.py script was broken.
- 1456_: [Linux] cpu_freq() returns None instead of 0.0 when min/max not
available (patch by Alex Manuskin)
- 1462_: [Linux] (tests) make tests invariant to LANG setting (patch by
Benjamin Drung)
- 1463_: cpu_distribution.py script was broken.
- 1470_: [Linux] disk_partitions(): fix corner case when /etc/mtab doesn't
exist. (patch by Cedric Lamoriniere)
- 1471_: [SunOS] Process name() and cmdline() can return SystemError. (patch
by Daniel Beer)
- 1472_: [Linux] cpu_freq() does not return all CPUs on Rasbperry-pi 3.
- 1474_: fix formatting of psutil.tests() which mimicks 'ps aux' output.
- 1475_: [Windows] OSError.winerror attribute wasn't properly checked resuling
in WindowsError being raised instead of AccessDenied.
- 1477_: [Windows] wrong or absent error handling for private NTSTATUS Windows
APIs. Different process methods were affected by this.
- 1480_: [Windows] psutil.cpu_count(logical=False) could cause a crash due to
fixed read violation. (patch by Samer Masterson)
- 1486_: [AIX, SunOS] AttributeError when interacting with Process methods
involved into oneshot() context.
- 1491_: [SunOS] net_if_addrs(): free() ifap struct on error. (patch by
Agnewee)
- 1493_: [Linux] cpu_freq(): handle the case where
/sys/devices/system/cpu/cpufreq/ exists but is empty.

5.6.1
=====
Expand Down
2 changes: 2 additions & 0 deletions MANIFEST.in
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,8 @@ include psutil/arch/windows/security.c
include psutil/arch/windows/security.h
include psutil/arch/windows/services.c
include psutil/arch/windows/services.h
include psutil/arch/windows/wmi.c
include psutil/arch/windows/wmi.h
include psutil/tests/README.rst
include psutil/tests/__init__.py
include psutil/tests/__main__.py
Expand Down
2 changes: 2 additions & 0 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,8 @@ CPU
>>> psutil.cpu_freq()
scpufreq(current=931.42925, min=800.0, max=3500.0)
>>>
>>> psutil.getloadavg() # also on Windows (emulated)
(3.14, 3.89, 4.67)
Memory
------
Expand Down
2 changes: 0 additions & 2 deletions docs/DEVNOTES
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,6 @@ FEATURES

- #613: thread names.

- #604: emulate os.getloadavg() on Windows

- scripts/taskmgr-gui.py (using tk).

- system-wide number of open file descriptors:
Expand Down
35 changes: 27 additions & 8 deletions docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,27 @@ CPU

.. versionchanged:: 5.5.1 added FreeBSD support.

.. function:: getloadavg()

Return the average system load over the last 1, 5 and 15 minutes as a tuple.
The load represents how many processes are waiting to be run by the
operating system.
On UNIX systems this relies on `os.getloadavg`_. On Windows this is
emulated by using a Windows API that spawns a thread which updates the
average every 5 seconds, mimicking the UNIX behavior. Thus, the first time
this is called and for the next 5 seconds it will return a meaningless
``(0.0, 0.0, 0.0)`` tuple. Example:

.. code-block:: python
>>> import psutil
>>> psutil.getloadavg()
(3.14, 3.89, 4.67)
Availability: Unix, Windows

.. versionadded:: 5.6.2

Memory
------

Expand Down Expand Up @@ -1264,14 +1285,14 @@ Process class
import psutil
p = psutil.Process()
if psutil.LINUX
p.ionice(psutil.IOPRIO_CLASS_RT, level=7)
p.ionice(psutil.IOPRIO_CLASS_RT, value=7)
else: # Windows
p.ionice(psutil.IOPRIO_HIGH)
p.ionice() # get

Availability: Linux, Windows Vista+

.. versionchanged:: 5.6.2 Windows accepts mew ``IOPRIO_*`` constants
.. versionchanged:: 5.6.2 Windows accepts new ``IOPRIO_*`` constants
including new ``IOPRIO_HIGH``.

.. method:: rlimit(resource, limits=None)
Expand Down Expand Up @@ -2556,12 +2577,6 @@ FAQs
the Python script as a Windows service (this is the trick used by tools
such as ProcessHacker).

----

* Q: What about load average?
* A: psutil does not expose any load average function as it's already available
in python as `os.getloadavg`_.

Running tests
=============

Expand All @@ -2583,6 +2598,10 @@ take a look at the `development guide`_.
Timeline
========

- 2019-0426:
`5.6.2 <https://pypi.org/project/psutil/5.6.2/#files>`__ -
`what's new <https://github.com/giampaolo/psutil/blob/master/HISTORY.rst#562>`__ -
`diff <https://github.com/giampaolo/psutil/compare/release-5.6.1...release-5.6.2#files_bucket>`__
- 2019-03-11:
`5.6.1 <https://pypi.org/project/psutil/5.6.1/#files>`__ -
`what's new <https://github.com/giampaolo/psutil/blob/master/HISTORY.rst#561>`__ -
Expand Down
15 changes: 13 additions & 2 deletions psutil/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,7 @@
"pid_exists", "pids", "process_iter", "wait_procs", # proc
"virtual_memory", "swap_memory", # memory
"cpu_times", "cpu_percent", "cpu_times_percent", "cpu_count", # cpu
"cpu_stats", # "cpu_freq",
"cpu_stats", # "cpu_freq", "getloadavg"
"net_io_counters", "net_connections", "net_if_addrs", # network
"net_if_stats",
"disk_io_counters", "disk_partitions", "disk_usage", # disk
Expand Down Expand Up @@ -2017,6 +2017,17 @@ def cpu_freq(percpu=False):
__all__.append("cpu_freq")


if hasattr(os, "getloadavg") or hasattr(_psplatform, "getloadavg"):
# Perform this hasattr check once on import time to either use the
# platform based code or proxy straight from the os module.
if hasattr(os, "getloadavg"):
getloadavg = os.getloadavg
else:
getloadavg = _psplatform.getloadavg

__all__.append("getloadavg")


# =====================================================================
# --- system memory related functions
# =====================================================================
Expand Down Expand Up @@ -2462,7 +2473,7 @@ def test(): # pragma: no cover
else:
cputime = ''

user = p.info['username']
user = p.info['username'] or ''
if not user and POSIX:
try:
user = p.uids()[0]
Expand Down
13 changes: 13 additions & 0 deletions psutil/_common.py
Original file line number Diff line number Diff line change
Expand Up @@ -619,3 +619,16 @@ def bytes2human(n, format="%(value).1f%(symbol)s"):
value = float(n) / prefix[symbol]
return format % locals()
return format % dict(symbol=symbols[0], value=n)


def get_procfs_path():
"""Return updated psutil.PROCFS_PATH constant."""
return sys.modules['psutil'].PROCFS_PATH


if PY3:
def decode(s):
return s.decode(encoding=ENCODING, errors=ENCODING_ERRS)
else:
def decode(s):
return s
32 changes: 10 additions & 22 deletions psutil/_psaix.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
"""AIX platform implementation."""

import errno
import functools
import glob
import os
import re
Expand All @@ -20,6 +21,7 @@
from . import _psutil_aix as cext
from . import _psutil_posix as cext_posix
from ._common import AF_INET6
from ._common import get_procfs_path
from ._common import memoize_when_activated
from ._common import NIC_DUPLEX_FULL
from ._common import NIC_DUPLEX_HALF
Expand Down Expand Up @@ -101,16 +103,6 @@
svmem = namedtuple('svmem', ['total', 'available', 'percent', 'used', 'free'])


# =====================================================================
# --- utils
# =====================================================================


def get_procfs_path():
"""Return updated psutil.PROCFS_PATH constant."""
return sys.modules['psutil'].PROCFS_PATH


# =====================================================================
# --- memory
# =====================================================================
Expand Down Expand Up @@ -331,7 +323,7 @@ def wrap_exceptions(fun):
"""Call callable into a try/except clause and translate ENOENT,
EACCES and EPERM in NoSuchProcess or AccessDenied exceptions.
"""

@functools.wraps(fun)
def wrapper(self, *args, **kwargs):
try:
return fun(self, *args, **kwargs)
Expand Down Expand Up @@ -366,20 +358,13 @@ def __init__(self, pid):
self._procfs_path = get_procfs_path()

def oneshot_enter(self):
self._proc_name_and_args.cache_activate(self)
self._proc_basic_info.cache_activate(self)
self._proc_cred.cache_activate(self)

def oneshot_exit(self):
self._proc_name_and_args.cache_deactivate(self)
self._proc_basic_info.cache_deactivate(self)
self._proc_cred.cache_deactivate(self)

@wrap_exceptions
@memoize_when_activated
def _proc_name_and_args(self):
return cext.proc_name_and_args(self.pid, self._procfs_path)

@wrap_exceptions
@memoize_when_activated
def _proc_basic_info(self):
Expand All @@ -394,14 +379,17 @@ def _proc_cred(self):
def name(self):
if self.pid == 0:
return "swapper"
# note: this is limited to 15 characters
return self._proc_name_and_args()[0].rstrip("\x00")
# note: max 16 characters
return cext.proc_name(self.pid, self._procfs_path).rstrip("\x00")

@wrap_exceptions
def exe(self):
# there is no way to get executable path in AIX other than to guess,
# and guessing is more complex than what's in the wrapping class
exe = self.cmdline()[0]
cmdline = self.cmdline()
if not cmdline:
return ''
exe = cmdline[0]
if os.path.sep in exe:
# relative or absolute path
if not os.path.isabs(exe):
Expand All @@ -423,7 +411,7 @@ def exe(self):

@wrap_exceptions
def cmdline(self):
return self._proc_name_and_args()[1].split(' ')
return cext.proc_args(self.pid)

@wrap_exceptions
def create_time(self):
Expand Down
27 changes: 10 additions & 17 deletions psutil/_pslinux.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@
from . import _psposix
from . import _psutil_linux as cext
from . import _psutil_posix as cext_posix
from ._common import ENCODING
from ._common import ENCODING_ERRS
from ._common import decode
from ._common import get_procfs_path
from ._common import isfile_strict
from ._common import memoize
from ._common import memoize_when_activated
Expand Down Expand Up @@ -207,19 +207,6 @@ class IOPriority(enum.IntEnum):
# =====================================================================


if PY3:
def decode(s):
return s.decode(encoding=ENCODING, errors=ENCODING_ERRS)
else:
def decode(s):
return s


def get_procfs_path():
"""Return updated psutil.PROCFS_PATH constant."""
return sys.modules['psutil'].PROCFS_PATH


def readlink(path):
"""Wrapper around os.readlink()."""
assert isinstance(path, basestring), path
Expand Down Expand Up @@ -681,7 +668,7 @@ def cpu_stats():
ctx_switches, interrupts, soft_interrupts, syscalls)


if os.path.exists("/sys/devices/system/cpu/cpufreq") or \
if os.path.exists("/sys/devices/system/cpu/cpufreq/policy0") or \
os.path.exists("/sys/devices/system/cpu/cpu0/cpufreq"):
def cpu_freq():
"""Return frequency metrics for all CPUs.
Expand Down Expand Up @@ -725,9 +712,15 @@ def cpu_freq():
for line in f:
if line.lower().startswith(b'cpu mhz'):
key, value = line.split(b'\t:', 1)
ret.append(_common.scpufreq(float(value), None, None))
ret.append(_common.scpufreq(float(value), 0., 0.))
return ret

else:
def cpu_freq():
"""Dummy implementation when none of the above files are present.
"""
return []


# =====================================================================
# --- network
Expand Down
Loading

0 comments on commit 68c12ae

Please sign in to comment.