Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Execute a Python script post install using distutils / setuptools

I'm trying to add a post-install task to Python distutils as described in How to extend distutils with a simple post install script?. The task is supposed to execute a Python script in the installed lib directory. This script generates additional Python modules the installed package requires.

My first attempt is as follows:

from distutils.core import setup from distutils.command.install import install  class post_install(install):     def run(self):         install.run(self)         from subprocess import call         call(['python', 'scriptname.py'],              cwd=self.install_lib + 'packagename')  setup(  ...  cmdclass={'install': post_install}, ) 

This approach works, but as far as I can tell has two deficiencies:

  1. If the user has used a Python interpreter other than the one picked up from PATH, the post install script will be executed with a different interpreter which might cause a problem.
  2. It's not safe against dry-run etc. which I might be able to remedy by wrapping it in a function and calling it with distutils.cmd.Command.execute.

How could I improve my solution? Is there a recommended way / best practice for doing this? I'd like to avoid pulling in another dependency if possible.

like image 286
kynan Avatar asked Jul 23 '13 09:07

kynan


People also ask

What is the use of setuptools in Python?

Setuptools is a package development process library designed to facilitate packaging Python projects by enhancing the Python standard library distutils (distribution utilities). It includes: Python package and module definitions. Distribution package metadata.

How do I import setuptools in Python?

Follow the below steps to install the Setuptools package on Linux using the setup.py file: Step 1: Download the latest source package of Setuptools for Python3 from the website. Step 3: Go to the setuptools-60.5. 0 folder and enter the following command to install the package.

What is Distutils in Python?

The distutils package provides support for building and installing additional modules into a Python installation. The new modules may be either 100%-pure Python, or may be extension modules written in C, or may be collections of Python packages which include modules coded in both Python and C.


2 Answers

The way to address these deficiences is:

  1. Get the full path to the Python interpreter executing setup.py from sys.executable.
  2. Classes inheriting from distutils.cmd.Command (such as distutils.command.install.install which we use here) implement the execute method, which executes a given function in a "safe way" i.e. respecting the dry-run flag.

    Note however that the --dry-run option is currently broken and does not work as intended anyway.

I ended up with the following solution:

import os, sys from distutils.core import setup from distutils.command.install import install as _install   def _post_install(dir):     from subprocess import call     call([sys.executable, 'scriptname.py'],          cwd=os.path.join(dir, 'packagename'))   class install(_install):     def run(self):         _install.run(self)         self.execute(_post_install, (self.install_lib,),                      msg="Running post install task")   setup(     ...     cmdclass={'install': install}, ) 

Note that I use the class name install for my derived class because that is what python setup.py --help-commands will use.

like image 197
kynan Avatar answered Sep 26 '22 14:09

kynan


I think the easiest way to perform the post-install, and keep the requirements, is to decorate the call to setup(...):

from setup tools import setup   def _post_install(setup):     def _post_actions():         do_things()     _post_actions()     return setup  setup = _post_install(     setup(         name='NAME',         install_requires=['...     ) ) 

This will run setup() when declaring setup. Once done with the requirements installation, it will run the _post_install() function, which will run the inner function _post_actions().

like image 27
Mbm Avatar answered Sep 25 '22 14:09

Mbm