[Python-checkins] cpython: Issue #17914: Add os.cpu_count(). Patch by Yogesh Chaudhari, based on an

charles-francois.natali python-checkins at python.org
Mon May 20 14:41:54 CEST 2013


http://hg.python.org/cpython/rev/5e0c56557390
changeset:   83858:5e0c56557390
user:        Charles-Francois Natali <cf.natali at gmail.com>
date:        Mon May 20 14:40:46 2013 +0200
summary:
  Issue #17914: Add os.cpu_count(). Patch by Yogesh Chaudhari, based on an
initial patch by Trent Nelson.

files:
  Doc/library/multiprocessing.rst |   3 +
  Doc/library/os.rst              |  11 ++-
  Lib/multiprocessing/__init__.py |  25 +------
  Lib/test/test_os.py             |  10 +++
  Misc/NEWS                       |   3 +
  Modules/posixmodule.c           |  68 +++++++++++++++++++++
  6 files changed, 94 insertions(+), 26 deletions(-)


diff --git a/Doc/library/multiprocessing.rst b/Doc/library/multiprocessing.rst
--- a/Doc/library/multiprocessing.rst
+++ b/Doc/library/multiprocessing.rst
@@ -702,6 +702,9 @@
    Return the number of CPUs in the system.  May raise
    :exc:`NotImplementedError`.
 
+   .. seealso::
+      :func:`os.cpu_count`
+
 .. function:: current_process()
 
    Return the :class:`Process` object corresponding to the current process.
diff --git a/Doc/library/os.rst b/Doc/library/os.rst
--- a/Doc/library/os.rst
+++ b/Doc/library/os.rst
@@ -3155,10 +3155,6 @@
    Return the set of CPUs the process with PID *pid* (or the current process
    if zero) is restricted to.
 
-   .. seealso::
-      :func:`multiprocessing.cpu_count` returns the number of CPUs in the
-      system.
-
 
 .. _os-path:
 
@@ -3196,6 +3192,13 @@
    Availability: Unix.
 
 
+.. function:: cpu_count()
+
+   Return the number of CPUs in the system. Returns None if undetermined.
+
+   .. versionadded:: 3.4
+
+
 .. function:: getloadavg()
 
    Return the number of processes in the system run queue averaged over the last
diff --git a/Lib/multiprocessing/__init__.py b/Lib/multiprocessing/__init__.py
--- a/Lib/multiprocessing/__init__.py
+++ b/Lib/multiprocessing/__init__.py
@@ -85,30 +85,11 @@
     '''
     Returns the number of CPUs in the system
     '''
-    if sys.platform == 'win32':
-        try:
-            num = int(os.environ['NUMBER_OF_PROCESSORS'])
-        except (ValueError, KeyError):
-            num = 0
-    elif 'bsd' in sys.platform or sys.platform == 'darwin':
-        comm = '/sbin/sysctl -n hw.ncpu'
-        if sys.platform == 'darwin':
-            comm = '/usr' + comm
-        try:
-            with os.popen(comm) as p:
-                num = int(p.read())
-        except ValueError:
-            num = 0
+    num = os.cpu_count()
+    if num is None:
+        raise NotImplementedError('cannot determine number of cpus')
     else:
-        try:
-            num = os.sysconf('SC_NPROCESSORS_ONLN')
-        except (ValueError, OSError, AttributeError):
-            num = 0
-
-    if num >= 1:
         return num
-    else:
-        raise NotImplementedError('cannot determine number of cpus')
 
 def freeze_support():
     '''
diff --git a/Lib/test/test_os.py b/Lib/test/test_os.py
--- a/Lib/test/test_os.py
+++ b/Lib/test/test_os.py
@@ -2216,6 +2216,15 @@
                 else:
                     self.fail("No exception thrown by {}".format(func))
 
+class CPUCountTests(unittest.TestCase):
+    def test_cpu_count(self):
+        cpus = os.cpu_count()
+        if cpus is not None:
+            self.assertIsInstance(cpus, int)
+            self.assertGreater(cpus, 0)
+        else:
+            self.skipTest("Could not determine the number of CPUs")
+
 @support.reap_threads
 def test_main():
     support.run_unittest(
@@ -2246,6 +2255,7 @@
         TermsizeTests,
         OSErrorTests,
         RemoveDirsTests,
+        CPUCountTests,
     )
 
 if __name__ == "__main__":
diff --git a/Misc/NEWS b/Misc/NEWS
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -99,6 +99,9 @@
 Library
 -------
 
+- Issue #17914: Add os.cpu_count(). Patch by Yogesh Chaudhari, based on an
+  initial patch by Trent Nelson.
+
 - Issue #17980: Fix possible abuse of ssl.match_hostname() for denial of
   service using certificates with many wildcards (CVE-2013-2099).
 
diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c
--- a/Modules/posixmodule.c
+++ b/Modules/posixmodule.c
@@ -113,6 +113,18 @@
 #include <dlfcn.h>
 #endif
 
+#ifdef __hpux
+#include <sys/mpctl.h>
+#endif
+
+#if defined(__DragonFly__) || \
+    defined(__OpenBSD__)   || \
+    defined(__FreeBSD__)   || \
+    defined(__NetBSD__)    || \
+    defined(__APPLE__)
+#include <sys/sysctl.h>
+#endif
+
 #if defined(MS_WINDOWS)
 #  define TERMSIZE_USE_CONIO
 #elif defined(HAVE_SYS_IOCTL_H)
@@ -10302,6 +10314,60 @@
 }
 #endif /* defined(TERMSIZE_USE_CONIO) || defined(TERMSIZE_USE_IOCTL) */
 
+PyDoc_STRVAR(posix_cpu_count__doc__,
+"cpu_count() -> integer\n\n\
+Return the number of CPUs in the system, or None if this value cannot be\n\
+established.");
+
+#if defined(__DragonFly__) || \
+    defined(__OpenBSD__)   || \
+    defined(__FreeBSD__)   || \
+    defined(__NetBSD__)    || \
+    defined(__APPLE__)
+static long
+_bsd_cpu_count(void)
+{
+    long ncpu = 0;
+    int mib[2];
+    size_t len = sizeof(int);
+
+    mib[0] = CTL_HW;
+    mib[1] = HW_NCPU;
+    if (sysctl(mib, 2, &ncpu, &len, NULL, 0) == 0)
+        return ncpu;
+    else
+        return 0;
+}
+#endif
+
+static PyObject *
+posix_cpu_count(PyObject *self)
+{
+    long ncpu = 0;
+#ifdef MS_WINDOWS
+    SYSTEM_INFO sysinfo;
+    GetSystemInfo(&sysinfo);
+    ncpu = sysinfo.dwNumberOfProcessors;
+#elif defined(__hpux)
+    ncpu = mpctl(MPC_GETNUMSPUS, NULL, NULL);
+#elif defined(HAVE_SYSCONF) && defined(_SC_NPROCESSORS_ONLN)
+    ncpu = sysconf(_SC_NPROCESSORS_ONLN);
+#elif defined(__APPLE__)
+    size_t len = sizeof(int);
+    if (sysctlnametomib("hw.logicalcpu", &ncpu, &len, NULL, 0) != 0)
+        ncpu = _bsd_cpu_count();
+#elif defined(__DragonFly__) || \
+      defined(__OpenBSD__)   || \
+      defined(__FreeBSD__)   || \
+      defined(__NetBSD__)
+    ncpu = _bsd_cpu_count();
+#endif
+    if (ncpu >= 1)
+        return PyLong_FromLong(ncpu);
+    else
+        Py_RETURN_NONE;
+}
+
 
 static PyMethodDef posix_methods[] = {
     {"access",          (PyCFunction)posix_access,
@@ -10747,6 +10813,8 @@
 #if defined(TERMSIZE_USE_CONIO) || defined(TERMSIZE_USE_IOCTL)
     {"get_terminal_size", get_terminal_size, METH_VARARGS, termsize__doc__},
 #endif
+    {"cpu_count", (PyCFunction)posix_cpu_count,
+                  METH_NOARGS, posix_cpu_count__doc__},
     {NULL,              NULL}            /* Sentinel */
 };
 

-- 
Repository URL: http://hg.python.org/cpython


More information about the Python-checkins mailing list