When to use os.name, sys.platform, or platform.system?
Asked Answered
E

6

144

As far as I know, Python has 3 ways of finding out what operating system is running on:

  1. os.name
  2. sys.platform
  3. 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.

Esteban answered 29/12, 2010 at 10:1 Comment(2)
use sys.platform.startswith('linux') instead of sys.platform == 'linux2' for future compatibilitySlashing
I do it this way: if sys.platform == "linux" or sys.platform == "linux2":Resting
D
91

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 runs uname 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.
Distributor answered 26/7, 2012 at 17:43 Comment(2)
I did more research and here is the detailed answer: https://mcmap.net/q/53315/-how-to-identify-which-os-python-is-running-on.Udine
Note that at least in Python 3.10 , platform.system defaults to sys.platform outside of Unix (in Unix it used uname).Statics
W
25

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.
Wherewithal answered 13/1, 2013 at 5:58 Comment(0)
S
12

From sys.platform docs:

  • os.name has a coarser granularity
  • os.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).

Slashing answered 26/7, 2012 at 15:21 Comment(0)
B
10

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.

Bligh answered 13/1, 2013 at 11:12 Comment(3)
os.name possible return values are 'posix', 'nt', 'java' according to Python 3 docs. See also: platform module docs. I do not believe 'riscos' and 'os2' are possible return values from os.name; they may be return values from sys.platform. The Python 3 sys.platform documentation does not appear to be exhaustive.Weakfish
@afeique: I updated my answer for newer Python, but it was right at that time. See Python 3.3 - os.name (the latest version at that time). Python 2.7 is still supported and 'riscos' is a possible value for it.Bligh
Thanks @hynekcer, I appreciate your edit to add Python version numbers. I apologize for not realizing it changed after Python 3.3. I did not peruse the different versions of the documentation and made the gross assumption that Python 3 behaviour of os.name was consistent across versions. I also did not double-check the 2.7 documentation, but I know now that you're correct.Weakfish
C
3

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.

Cyton answered 29/12, 2010 at 10:5 Comment(1)
I wonder if we can get any Python developers to confirm this. Maybe even whoever developed the platform module.Esteban
Y
0

sys.platform is determined at compile time, platform.system() determines at run time.

This means the former usage has the ability to check syntax and dim unreachable code blocks in IDE.

IMO, if sys.platform can meet your needs and works fine in your code, use it.

Youngman answered 30/1, 2023 at 4:31 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.