LucillaMicali
LucillaMicali

Reputation: 1

Linux package management with Python

I am a complete Python beginner and try to write a Python script to automate the setup of a SDK on Linux machines from remote Github repositories.

The script starts by performing some basic preliminary operations, especially the check/setup of several packages (git, docker, pip, etc.).

For now, I target Debian (Stretch, Buster), Centos (6, 7) and Ubuntu Server 18.04LTS. Of course, I want the script to run on the widest range of linux machines.

Today I rely on available package managers (apt-get and yum), roughly requested through subprocess.call() statements.

I customize the related commands using nasty script configuration variables like below :

    import platform

    distribution                    = platform.dist()[0]
    version                         = platform.dist()[1]

    if      distribution == 'debian':
            pkgInstaller            = 'dpkg'
            pkmManager              = 'apt-get'
            checkIfInstalled        = '-s'
            installPackage          = 'install'
            yesToAll                = '-y'
            dockerPackage           = 'docker-ce'
    elif    distribution == 'centos':
            pkgInstaller            = 'rpm'
            pkgManager              = 'yum'
            checkIfInstalled        = '-q'
            installPackage          = 'install'
            yesToAll                = '-y'
            dockerPackage           = 'docker'

I then simply loop on an array containing the names of packages to be installed, then run the command through subprocess.call() :

    prerequisites                   = ['git', dockerPackage, 'doxygen', 'python2-pip']

    for pkg in prerequisites:
        pgkInstallation = subprocess.call(['sudo', pkgManager, yesToAll, installPackage, pkg])

While this approach may have the benefit of not having too much bonding to third-party Python modules, I guess there are... some smarter ways of doing such simple operation ?

Upvotes: 0

Views: 496

Answers (1)

C.Nivs
C.Nivs

Reputation: 13106

Usually when doing switch statements like this, a dictionary might be a bit more useful. Also, normally I'm not one to try to PEP-8 things, but this is an instance where PEP-8 might really help your readability by not matching up your equals signs for all of your lines of code.

The dict will hold your distro as the key, and your vars as a value wrapped in a tuple

options = {
    'debian': ('dpkg', 'apt-get', '-s', 'install', '-y', 'docker-ce'),
    'centos': ('rpm', 'yum', '-q', 'install', '-y', 'docker'),
    }

# unpack this function call here
distribution, version, *_ = platform.dist() 


# now get the match
pkg_installer, pkg_manager, check, install_pkg, yes_to_all, docker = options[distribution]

requisites = ['git', docker, 'doxygen', 'python2-pip']

for pkg in requisites:
    pgkInstallation = subprocess.call(['sudo', pkg_manager, yes_to_all, install_pkg, pkg])

The options[distribution] call will raise a KeyError for unsupported distributions, so you can probably catch that and raise something a bit more useful like:

try:
    pkg_installer, pkg_manager, check, install_pkg, yes_to_all, docker = options[distribution]
except KeyError as e:
    raise ValueError(f"Got unsupported OS, expected one of {', '.join(options.keys())}") from e

To make it less verbose, the only var you use out of order is docker, so you can house all of the others in a single var:

try:
    *args, docker = options[distribution]
except KeyError as e:
    raise ValueError(f"Got unsupported OS, expected one of {', '.join(options.keys())}") from e

requisites = ['git', docker, 'doxygen', 'python2-pip']

for pkg in requisites:
    pgkInstallation = subprocess.call(['sudo', *args, pkg])

Upvotes: 1

Related Questions