Search code examples
pythonsetuptoolssetup.pypypidistutils

setup.py install os dependency


I want to make a distributable package. And my package depends on some OS package

Here what I want to install:

def install_libmagic():
    if sys.platform == 'darwin':
        subprocess.run(['brew', 'install', 'libmagic'])
    elif sys.platform == 'linux':
        subprocess.run(['apt-get', 'update'])
        subprocess.run(['apt-get', 'install', '-y', 'libmagic1'])
    else:
        raise Exception(f'Unknown system: {sys.platform}, can not install libmagic')

I want this code to be executed only when smb call: pip install mypacakge

I don't want it to be executed when I run: python setup.py bdist_wheel

How can I achieve this?

I tried this:

setup(
    ...
    install_requires=install_libmagic(),
)

Also tried to override install command:

from setuptools.command.install import install

class MyInstall(install):
    def run(self):
        install_libmagic()
        install.run(self)
setup(
    ...
    cmdclass={'install': MyInstall}
)

But the function was executed on python setup.py bdist_wheel, which is not what I am trying to achieve.


Solution

  • I think you're mixing up the behaviors of built distributions (wheels) and source distributions.

    If your goal is run some subprocesses at install time, then you can't do this with a built distribution. A built distribution executes no Python code at install time. It only executes setup.py at build time, which is why you're seeing your functions executed when you call python setup.py bdist_wheel.

    On the other hand, a source distribution (python setup.py sdist) does execute the setup.py file at both build time and install time (roughly the same as python setup.py install) and would give you the behavior you're looking for.

    However, as the comments have already mentioned, this is going to be very fragile and not very user-friendly or portable. What you're describing is really a distro/OS package that contains some Python module, and you'd probably be better off with that instead.