diff options
author | Giampaolo Rodola <g.rodola@gmail.com> | 2018-10-16 21:17:52 +0200 |
---|---|---|
committer | Giampaolo Rodola <g.rodola@gmail.com> | 2018-10-16 21:17:52 +0200 |
commit | 8b465260638cde5370808e23eb9ace608141393a (patch) | |
tree | b5efb7f87bb047368d13dade411c19efd551b27b | |
parent | 2f9dcf3c7b37d4da155df62bc835ddbdfe10b24f (diff) | |
download | psutil-8b465260638cde5370808e23eb9ace608141393a.tar.gz |
#1197 / linux / cpu_freq(): parse /proc/cpuinfo in case /sys/devices/system/cpu fs is not available
-rw-r--r-- | HISTORY.rst | 2 | ||||
-rw-r--r-- | psutil/__init__.py | 16 | ||||
-rw-r--r-- | psutil/_pslinux.py | 13 | ||||
-rwxr-xr-x | psutil/tests/test_linux.py | 29 |
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'): |