Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions Doc/library/platform.rst
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,10 @@ Cross Platform
platforms do not provide this information or simply return the same value as for
:func:`machine`. NetBSD does this.

.. versionchanged:: 3.8
Where available (Linux), the processor information is now retrieved from
the "model name" of ``/proc/cpuinfo`` instead of from the output of
``uname -p``.

.. function:: python_build()

Expand Down
118 changes: 59 additions & 59 deletions Lib/platform.py
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,8 @@
import os
import re
import sys
import subprocess
import contextlib

### Globals & Constants

Expand Down Expand Up @@ -579,22 +581,6 @@ def _follow_symlinks(filepath):
os.path.join(os.path.dirname(filepath), os.readlink(filepath)))
return filepath

def _syscmd_uname(option, default=''):

""" Interface to the system's uname command.
"""
if sys.platform in ('dos', 'win32', 'win16'):
# XXX Others too ?
return default

import subprocess
try:
output = subprocess.check_output(('uname', option),
stderr=subprocess.DEVNULL,
text=True)
except (OSError, subprocess.CalledProcessError):
return default
return (output.strip() or default)

def _syscmd_file(target, default=''):

Expand Down Expand Up @@ -715,13 +701,58 @@ def architecture(executable=sys.executable, bits='', linkage=''):

return bits, linkage


def _get_machine_win32():
# Try to use the PROCESSOR_* environment variables
# available on Win XP and later; see
# http://support.microsoft.com/kb/888731 and
# http://www.geocities.com/rick_lively/MANUALS/ENV/MSWIN/PROCESSI.HTM

# WOW64 processes mask the native architecture
return (
os.environ.get('PROCESSOR_ARCHITEW6432', '') or
os.environ.get('PROCESSOR_ARCHITECTURE', '')
)


class _Processor:
@classmethod
def get(cls):
func = getattr(cls, f'get_{sys.platform}', cls.from_cpu_info)
return func() or ''

def get_win32():
return os.environ.get('PROCESSOR_IDENTIFIER', _get_machine_win32())

def get_darwin():
cmd = 'sysctl -n machdep.cpu.brand_string'.split()
return subprocess.check_output(cmd, text=True).strip()

def get_OpenVMS():
try:
import vms_lib
except ImportError:
pass
else:
csid, cpu_number = vms_lib.getsyi('SYI$_CPU', 0)
return 'Alpha' if cpu_number >= 128 else 'VAX'

def from_cpu_info():
pattern = re.compile(r'model name\s+: (.*)')
with contextlib.suppress(Exception):
with open('/proc/cpuinfo') as lines:
matched = next(filter(pattern.match, lines))
return pattern.match(matched).group(1)


### Portable uname() interface

uname_result = collections.namedtuple("uname_result",
"system node release version machine processor")

_uname_cache = None


def uname():

""" Fairly portable uname interface. Returns a tuple
Expand All @@ -735,7 +766,6 @@ def uname():

"""
global _uname_cache
no_os_uname = 0

if _uname_cache is not None:
return _uname_cache
Expand All @@ -744,43 +774,24 @@ def uname():

# Get some infos from the builtin os.uname API...
try:
system, node, release, version, machine = os.uname()
system, node, release, version, machine = infos = os.uname()
except AttributeError:
no_os_uname = 1

if no_os_uname or not list(filter(None, (system, node, release, version, machine))):
# Hmm, no there is either no uname or uname has returned
#'unknowns'... we'll have to poke around the system then.
if no_os_uname:
system = sys.platform
release = ''
version = ''
node = _node()
machine = ''
system = sys.platform
node = _node()
release = version = machine = ''
infos = ()

use_syscmd_ver = 1
if not any(infos):
# uname is not available

# Try win32_ver() on win32 platforms
if system == 'win32':
release, version, csd, ptype = win32_ver()
if release and version:
use_syscmd_ver = 0
# Try to use the PROCESSOR_* environment variables
# available on Win XP and later; see
# http://support.microsoft.com/kb/888731 and
# http://www.geocities.com/rick_lively/MANUALS/ENV/MSWIN/PROCESSI.HTM
if not machine:
# WOW64 processes mask the native architecture
if "PROCESSOR_ARCHITEW6432" in os.environ:
machine = os.environ.get("PROCESSOR_ARCHITEW6432", '')
else:
machine = os.environ.get('PROCESSOR_ARCHITECTURE', '')
if not processor:
processor = os.environ.get('PROCESSOR_IDENTIFIER', machine)
machine = machine or _get_machine_win32()

# Try the 'ver' system command available on some
# platforms
if use_syscmd_ver:
if not (release and version):
system, release, version = _syscmd_ver(system)
# Normalize system to what win32_ver() normally returns
# (_syscmd_ver() tends to return the vendor name as well)
Expand Down Expand Up @@ -820,20 +831,9 @@ def uname():
if not release or release == '0':
release = version
version = ''
# Get processor information
try:
import vms_lib
except ImportError:
pass
else:
csid, cpu_number = vms_lib.getsyi('SYI$_CPU', 0)
if (cpu_number >= 128):
processor = 'Alpha'
else:
processor = 'VAX'
if not processor:
# Get processor information from the uname system command
processor = _syscmd_uname('-p', '')

# Get processor information
processor = _Processor.get()

#If any unknowns still exist, replace them with ''s, which are more portable
if system == 'unknown':
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
:module:`platform` module no longer relies on the ``uname`` executable to
resolve processor information. Processor information on Linux systems is now
resolved to more useful information from the "model name" as found in
``/proc/cpuinfo``.