When to use os.name, sys.platform, or platform.system?
PythonOperating SystemPython ImportPython Problem Overview
As far as I know, Python has 3 ways of finding out what operating system is running on:
os.name
sys.platform
platform.system()
Knowing this information is often useful in conditional imports, or using functionality that differs between platforms (e.g. time.clock()
on Windows v.s. time.time()
on UNIX).
My question is, why 3 different ways of doing this? When should one way be used and not another? Which way is the 'best' (most future-proof or least likely to accidentally exclude a particular system which your program can actually run on)?
It seems like sys.platform
is more specific than os.name
, allowing you to distinguish win32
from cygwin
(as opposed to just nt
), and linux2
from darwin
(as opposed to just posix
). But if that's so, that what about the difference between sys.platform
and platform.system()
?
For example, which is better, this:
import sys
if sys.platform == 'linux2':
# Do Linux-specific stuff
or this? :
import platform
if platform.system() == 'Linux':
# Do Linux-specific stuff
For now I'll be sticking to sys.platform
, so this question isn't particularly urgent, but I would be very grateful for some clarification regarding this.
Python Solutions
Solution 1 - Python
Dived a bit into the source code.
The output of sys.platform
and os.name
are determined at compile time. platform.system()
determines the system type at run time.
sys.platform
is specified as a compiler define during the build configuration.os.name
checks whether certain os specific modules are available (e.g.posix
,nt
, ...)platform.system()
actually runsuname
and potentially several other functions to determine the system type at run time.
My suggestion:
- Use
os.name
to check whether it's a posix-compliant system. - Use
sys.platform
to check whether it's a linux, cygwin, darwin, atheos, etc. - Use
platform.system()
if you don't believe the other sources.
Solution 2 - Python
There is a thin line difference between platform.system()
and sys.platform
and interestingly for most cases platform.system()
degenerates to sys.platform
Here is what the Source Python2.7\Lib\Platform.py\system
says
def system():
""" Returns the system/OS name, e.g. 'Linux', 'Windows' or 'Java'.
An empty string is returned if the value cannot be determined.
"""
return uname()[0]
def uname():
# Get some infos from the builtin os.uname API...
try:
system,node,release,version,machine = os.uname()
except AttributeError:
no_os_uname = 1
if no_os_uname or not 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 = ''
Also per the documentation
> os.uname() > > Return a 5-tuple containing information identifying the current operating system. The tuple contains 5 strings: (sysname, nodename, > release, version, machine). Some systems truncate the nodename to 8 > characters or to the leading component; a better way to get the > hostname is socket.gethostname() or even > socket.gethostbyaddr(socket.gethostname()). > > Availability: recent flavors of Unix.
Solution 3 - Python
From sys.platform
docs:
os.name
has a coarser granularityos.uname()
gives system-dependent version information- The
platform
module provides detailed checks for the system’s identity
Often the "best" future-proof way to test whether some functionality is available is just to try to use it and use a fallback if it fails.
> what about the difference between sys.platform and platform.system()?
platform.system()
returns a normalized value that it might get from several sources: os.uname()
, sys.platform
, ver
command (on Windows).
Solution 4 - Python
It depends on whether you prefer raising exception or trying anything on an untested system and whether your code is so high level or so low level that it can or can't work on a similar untested system (e.g. untested Mac - 'posix' or on embedded ARM systems). More pythonic is to not enumerate all known systems but to test possible relevant properties. (e.g. it is considered important the endianess of the system but unimportant multiprocessing properties.)
-
os.name is a sufficient resolution for the correct usage of
os
module. Possible values are 'posix', 'nt', 'os2', 'ce', 'java' or 'riscos' in Python 2.7, while only the 'posix', 'nt' and 'java' are used since Python 3.4. -
sys.platform is a finer resolution. It is recommended to use
if sys.platform.startswith('linux')
idiom because "linux2" means a Linux kernel version 2.xx or 3. Older kernels are currently never used. In Python 3.3 are all Linux systems simple 'linux'.
I do not know the specifics of "Mac" and "Java" systems and so I can not use the results of very good method platform.system() for branching, but I would use advantages of the platform
module for messages and error logging.
Solution 5 - Python
I believe the platform module is probably preferred for new code. The others existed before it. It is an evolution, and the others remain for backwards compatibility.