Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Post-install script with Python setuptools

Is it possible to specify a post-install Python script file as part of the setuptools setup.py file so that a user can run the command:

python setup.py install 

on a local project file archive, or

pip install <name> 

for a PyPI project and the script will be run at the completion of the standard setuptools install? I am looking to perform post-install tasks that can be coded in a single Python script file (e.g. deliver a custom post-install message to the user, pull additional data files from a different remote source repository).

I came across this SO answer from several years ago that addresses the topic and it sounds as though the consensus at that time was that you need to create an install subcommand. If that is still the case, would it be possible for someone to provide an example of how to do this so that it is not necessary for the user to enter a second command to run the script?

like image 419
Chris Simpkins Avatar asked Nov 29 '13 15:11

Chris Simpkins


People also ask

Does pip install setuptools?

Type “ pip install setuptools ” (without quotes) in the command line and hit Enter again. This installs setuptools for your default Python installation. The previous command may not work if you have both Python versions 2 and 3 on your computer.

Does Python include setuptools?

the setuptools is not part of the python vanilla codebase, hence not a vanilla modules. python.org installers or mac homebrew will install it for you, but if someone compile the python by himself or install it on some linux distribution he may not get it and will need to install it by himself.


2 Answers

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 setup from setuptools.command.develop import develop from setuptools.command.install import install   class PostDevelopCommand(develop):     """Post-installation for development mode."""     def run(self):         develop.run(self)         # PUT YOUR POST-INSTALL SCRIPT HERE or CALL A FUNCTION  class 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 setup from setuptools.command.develop import develop from setuptools.command.install import install from subprocess import check_call   class 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.

like image 98
mertyildiran Avatar answered Sep 21 '22 08:09

mertyildiran


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 atexit from setuptools.command.install import install   def _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}, 
like image 38
Apalala Avatar answered Sep 17 '22 08:09

Apalala