There are some circumstances where developing platform-specific code is simply unavoidable, either because a high-level library is not available or because the actions that must be taken are fundamentally different.
In this situation, it is essential to detect the platform.
There are a few ways of doing this in Python, including os.system()
and sys.platform
, but the platform
module contains the best set of functionality for determining the OS details most useful in making decisions.
The platform
module provides a number of functions that can be used to obtain information about the current platform.
Detecting the Operating System
The platform.system()
function returns a string identifying the underlying operating system ( Windows, Linux, freebsd7, or Darwin (for macOS)).
For example, on a Windows 10 machine, the following code returns Windows
.
import platform
platform.system()
On a linux machine, the same code returns Linux
. On a macOS machine, it returns Darwin
.
Detecting the Architecture
The architecture of a machine is the bitness of the processor, which is either 32-bit or 64-bit.
The platform.architecture()
function returns a tuple containing the architecture and the linkage format of the current Python interpreter.
import platform
print(platform.architecture())
For example on a 64-bit Windows machine, the output is:
('64bit', 'WindowsPE')
On a 32-bit Linux machine, the output is:
('32bit', 'ELF')
On a 64-bit Linux machine, the output is:
('64bit', 'ELF')
Detecting the Machine
The machine type is the type of processor, such as x86_64
or AMD64
.
The platform.machine()
function returns a string identifying the underlying machine type, e.g. ‘i386’, ‘x86_64’, ‘Power Macintosh’, or ‘AMD64’.
import platform
print(platform.machine())
For example, on a 64-bit Windows machine, the output is:
AMD64
On a 32-bit Linux machine, the output is:
i686
On a 64-bit Linux machine, the output is:
x86_64
Detecting the OS Version
The OS version refers to the version of the operating system, such as Windows version 10
or Ubuntu version 20.04
.
The platform.version()
function returns a string identifying the version of the underlying operating system.
import platform
print(platform.version())
For example, on a Windows 10 machine, the output is:
10.0.19042
On a Linux machine, the output is:
#1 SMP Tue Aug 11 13:02:50 UTC 2020
On a macOS machine, the output is:
Darwin Kernel Version 19.6.0: Thu Aug 20 20:55:26 PDT 2020; root:xnu-6153.141.2~1/RELEASE_X86_64
Running a command based on the OS
Simple use case
For simple cases a simple if else statement can be used to run a command based on the OS.
import platform
import subprocess
os_name = platform.system()
if os_name in ('Darwin', 'freebsd7'):
# detects macOS and freebsd7
cmd = ['ps', '-e', '-o', "comm=''", '-c']
elif os_name == 'Linux':
# detects Linux
cmd = ['ps', '-e', '--format', 'comm', '--no-heading']
elif os_name == 'Windows':
# detects Windows
cmd = ['tasklist', '/nh', '/fo', 'CSV']
else:
raise NotImplemented("Command unknown for OS")
processes = subprocess.check_output(cmd)
print(processes)
In the above code, the platform.system()
function is used to detect the OS. Then, based on the OS, the appropriate command is run using the subprocess
module. The cmd variable is a list of strings, where the first string is the command and the rest are the arguments.
If you want to write less code and make it more readable, you can use a dictionary to map the OS to the command.
import platform
import subprocess
commands = {
'Darwin': ['ps', '-e', '-o', "comm=''", '-c'],
'freebsd7': ['ps', '-e', '-o', "comm=''", '-c'],
'Linux': ['ps', '-e', '--format', 'comm', '--no-heading'],
'Windows': ['tasklist', '/nh', '/fo', 'CSV']
}
os_name = platform.system()
cmd = commands[os_name]
processes = subprocess.check_output(cmd)
print(processes)
Advanced use case
For more complex situations, it makes sense to bundle platform-specific code into backend classes.
To begin, create a backend.py
file. Then define a genericBackend class which will be the base class for all platform-specific backends.
import subprocess
class GenericBackend():
cmd = []
def get_process_list(self):
if self.cmd:
return subprocess.check_output(self.cmd)
else :
raise NotImplemented
Then, define a class (subclass) for each platform you want to support.
class LinuxBackend(GenericBackend):
cmd = ['ps', '-e', '--format', 'comm', '--no-heading']
class WindowsBackend(GenericBackend):
cmd = ['tasklist', '/nh', '/fo', 'CSV']
class MacBackend(GenericBackend):
cmd = ['ps', '-e', '-o', "comm=''", '-c']
Finally, define a function which will return the appropriate backend class by taking the OS name as an argument.
def get_backend(os_name):
backends = {'Linux': LinuxBackend, 'Darwin': MacBsdBackend, 'Windows': WindowsBackend, 'freebsd7': MacBsdBackend}
try:
return backends[os_name]
except KeyError:
raise NotImplemented("No backend for OS")
You can create a simple main.py file that will use the above code..
import platform
from backend import get_backend
os_name = platform.system()
os_backend = get_backend(os_name)()
print(os_backend.get_process_list())
Conclusion
In this article, you learned how to detect the OS, architecture, and version of a machine using the platform
module. You also learned how to run a command based on the OS using the platform
module and the subprocess
module. You also learned how to write platform-specific code using the platform
module and classes.