Post-install script with Python setuptools
Note: The solution below only works when installing a source distribution zip or tarball, or installing in editable mode from a source tree. It will not work when installing from a binary wheel (.whl
)
This solution is more transparent:
You will make a few additions to setup.py
and there is no need for an extra file.
Also you need to consider two different post-installations; one for development/editable mode and the other one for install mode.
Add these two classes that includes your post-install script to setup.py
:
from setuptools import setupfrom setuptools.command.develop import developfrom setuptools.command.install import installclass PostDevelopCommand(develop): """Post-installation for development mode.""" def run(self): develop.run(self) # PUT YOUR POST-INSTALL SCRIPT HERE or CALL A FUNCTIONclass PostInstallCommand(install): """Post-installation for installation mode.""" def run(self): install.run(self) # PUT YOUR POST-INSTALL SCRIPT HERE or CALL A FUNCTION
and insert cmdclass
argument to setup()
function in setup.py
:
setup( ... cmdclass={ 'develop': PostDevelopCommand, 'install': PostInstallCommand, }, ...)
You can even call shell commands during installation, like in this example which does pre-installation preparation:
from setuptools import setupfrom setuptools.command.develop import developfrom setuptools.command.install import installfrom subprocess import check_callclass PreDevelopCommand(develop): """Pre-installation for development mode.""" def run(self): check_call("apt-get install this-package".split()) develop.run(self)class PreInstallCommand(install): """Pre-installation for installation mode.""" def run(self): check_call("apt-get install this-package".split()) install.run(self)setup( ...
P.S. there are no any pre-install entry points available on setuptools. Read this discussion if you are wondering why there is none.
Note: The solution below only works when installing a source distribution zip or tarball, or installing in editable mode from a source tree. It will not work when installing from a binary wheel (.whl
)
This is the only strategy that has worked for me when the post-install script requires that the package dependencies have already been installed:
import atexitfrom setuptools.command.install import installdef _post_install(): print('POST INSTALL')class new_install(install): def __init__(self, *args, **kwargs): super(new_install, self).__init__(*args, **kwargs) atexit.register(_post_install)setuptools.setup( cmdclass={'install': new_install},
Note: The solution below only works when installing a source distribution zip or tarball, or installing in editable mode from a source tree. It will not work when installing from a binary wheel (.whl
)
A solution could be to include a post_setup.py
in setup.py
's directory. post_setup.py
will contain a function which does the post-install and setup.py
will only import and launch it at the appropriate time.
In setup.py
:
from distutils.core import setupfrom distutils.command.install_data import install_datatry: from post_setup import main as post_installexcept ImportError: post_install = lambda: Noneclass my_install(install_data): def run(self): install_data.run(self) post_install()if __name__ == '__main__': setup( ... cmdclass={'install_data': my_install}, ... )
In post_setup.py
:
def main(): """Do here your post-install""" passif __name__ == '__main__': main()
With the common idea of launching setup.py
from its directory, you will be able to import post_setup.py
else it will launch an empty function.
In post_setup.py
, the if __name__ == '__main__':
statement allows you to manually launch post-install from command line.