summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGiampaolo Rodola <g.rodola@gmail.com>2018-10-16 21:17:52 +0200
committerGiampaolo Rodola <g.rodola@gmail.com>2018-10-16 21:17:52 +0200
commit8b465260638cde5370808e23eb9ace608141393a (patch)
treeb5efb7f87bb047368d13dade411c19efd551b27b
parent2f9dcf3c7b37d4da155df62bc835ddbdfe10b24f (diff)
downloadpsutil-8b465260638cde5370808e23eb9ace608141393a.tar.gz
#1197 / linux / cpu_freq(): parse /proc/cpuinfo in case /sys/devices/system/cpu fs is not available
-rw-r--r--HISTORY.rst2
-rw-r--r--psutil/__init__.py16
-rw-r--r--psutil/_pslinux.py13
-rwxr-xr-xpsutil/tests/test_linux.py29
4 files changed, 58 insertions, 2 deletions
diff --git a/HISTORY.rst b/HISTORY.rst
index 4b2e7ed2..44837094 100644
--- a/HISTORY.rst
+++ b/HISTORY.rst
@@ -7,6 +7,8 @@ XXXX-XX-XX
**Enhancements**
+- 1197_: [Linux] cpu_freq() is now implemented by parsing /proc/cpuinfo in case
+ /sys/devices/system/cpu/* filesystem is not available.
- 1310_: [Linux] psutil.sensors_temperatures() now parses /sys/class/thermal
in case /sys/class/hwmon fs is not available (e.g. Raspberry Pi). (patch
by Alex Manuskin)
diff --git a/psutil/__init__.py b/psutil/__init__.py
index f43ef7b6..c2a83fb1 100644
--- a/psutil/__init__.py
+++ b/psutil/__init__.py
@@ -1861,13 +1861,25 @@ if hasattr(_psplatform, "cpu_freq"):
return ret[0]
else:
currs, mins, maxs = 0.0, 0.0, 0.0
+ set_none = False
for cpu in ret:
currs += cpu.current
+ # On Linux if /proc/cpuinfo is used min/max are set
+ # to None.
+ if LINUX and cpu.min is None:
+ set_none = True
+ continue
mins += cpu.min
maxs += cpu.max
+
current = currs / num_cpus
- min_ = mins / num_cpus
- max_ = maxs / num_cpus
+
+ if set_none:
+ min_ = max_ = None
+ else:
+ min_ = mins / num_cpus
+ max_ = maxs / num_cpus
+
return _common.scpufreq(current, min_, max_)
__all__.append("cpu_freq")
diff --git a/psutil/_pslinux.py b/psutil/_pslinux.py
index a69b1d66..1520261c 100644
--- a/psutil/_pslinux.py
+++ b/psutil/_pslinux.py
@@ -704,6 +704,19 @@ if os.path.exists("/sys/devices/system/cpu/cpufreq") or \
ret.append(_common.scpufreq(curr, min_, max_))
return ret
+elif os.path.exists("/proc/cpuinfo"):
+ def cpu_freq():
+ """Alternate implementation using /proc/cpuinfo.
+ min and max frequencies are not available and are set to None.
+ """
+ ret = []
+ with open_binary('%s/cpuinfo' % get_procfs_path()) as f:
+ 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))
+ return ret
+
# =====================================================================
# --- network
diff --git a/psutil/tests/test_linux.py b/psutil/tests/test_linux.py
index 4e4bd565..115a6af8 100755
--- a/psutil/tests/test_linux.py
+++ b/psutil/tests/test_linux.py
@@ -704,6 +704,35 @@ class TestSystemCPU(unittest.TestCase):
self.assertEqual(len(flags), 2)
@unittest.skipIf(not HAS_CPU_FREQ, "not supported")
+ def test_cpu_freq_use_cpuinfo(self):
+ # Emulate a case where /sys/devices/system/cpu/cpufreq* does not
+ # exist and /proc/cpuinfo is used instead.
+ def path_exists_mock(path):
+ if path.startswith('/sys/devices/system/cpu/'):
+ return False
+ else:
+ if path == "/proc/cpuinfo":
+ flags.append(None)
+ return os_path_exists(path)
+
+ flags = []
+ os_path_exists = os.path.exists
+ try:
+ with mock.patch("os.path.exists", side_effect=path_exists_mock):
+ reload_module(psutil._pslinux)
+ ret = psutil.cpu_freq()
+ assert ret
+ assert flags
+ self.assertIsNone(ret.min)
+ self.assertIsNone(ret.max)
+ for freq in psutil.cpu_freq(percpu=True):
+ self.assertIsNone(freq.min)
+ self.assertIsNone(freq.max)
+ finally:
+ reload_module(psutil._pslinux)
+ reload_module(psutil)
+
+ @unittest.skipIf(not HAS_CPU_FREQ, "not supported")
def test_cpu_freq_emulate_data(self):
def open_mock(name, *args, **kwargs):
if name.endswith('/scaling_cur_freq'):