Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Detect python package installation path from within setup.py

After installation, I would like to make soft-links to some of the configuration & data files created by installation.

How can I determine the location of a new package's files installed from within the package's setup.py?

I initially hard-coded the path "/usr/local/lib/python2.7/dist-packages", but that broke when I tried using a virtual environment. (Created by virtualenv.)

I tried distutils.sysconfig.get_python_lib(), and that works inside the virtualenv. When installed on the real system, however, it returns "/usr/lib/python2.7/dist-packages" (Note the "local" directory isn't present.)

I've also tried site.getsitepackages():

Running a Python shell from the base environment:

import site

site.getusersitepackages()

'/home/sarah/.local/lib/python2.7/site-packages'

site.getsitepackages()

['/usr/local/lib/python2.7/dist-packages', '/usr/lib/python2.7/dist-packages']

Running a Python shell from a virtual environment "testenv":

import site

site.getsitepackages()

Traceback (most recent call last):

File "", line 1, in

AttributeError: 'module' object has no attribute 'getsitepackages'

I'm running "Python 2.7.3 (default, Aug 1 2012, 05:14:39)" with "[GCC 4.6.3] on linux2" on Ubuntu. I can probably cobble something together with try-except blocks, but it seems like there should be some variable set / returned by distutils / setuptools. (I'm agnostic about which branch to use, as long as it works.)

Thanks.

like image 903
Sarah Messer Avatar asked Jun 10 '13 18:06

Sarah Messer


People also ask

Does pip install use setup py?

@joeforker, pip uses setup.py behind the scenes.

How do I install a package using setup py?

Installing Python Packages with Setup.py To install a package that includes a setup.py file, open a command or terminal window and: cd into the root directory where setup.py is located. Enter: python setup.py install.


1 Answers

I haven't found the "correct" way of doing this, but I have found a couple tricks that seem almost-correct. One method only works on install; the other only works if the package is already installed.

For install, I use the object returned by setuptools.setup():

from setuptools import setup
s = setup([...])
installation_path = s.command_obj['install'].install_lib

(This only works during install since you need a valid Distribution object for those attributes to exist. AFAIK, the only way to get such an object is to run setup().)

On uninstall, I use the file attribute of the package, as suggested by @Zhenya above. The only catch is that when I run ./setup.py uninstall to get rid of package, I usually have directories ./package/, ./build, ./dist, and ./package.egg-info/. (The "uninstall" option is caught by my code without calling setup(). It runs a manually-created script to delete the package files.) These can redirect the python interpreter to some place other than the globally-accessible repository I'm trying to get rid of. Here's my hack to handle that:

import imp
import sys
from subprocess import Popen
from os import getcwd
Popen('rm -r build dist *.egg-info', shell=True).wait()
oldpath = sys.path
rundir = getcwd()
sys.path.remove(rundir)
mod = imp.find_module(PACKAGE)
p = imp.load_module(PACKAGE, mod[0], mod[1], mod[2])
sys.path = oldpath
installation_path = p.__file__

(This doesn't work during install since - I think - Python only inventories modules when it starts, so find_module() won't find the just-installed package unless you exit python and come back in.)

I've tested both install and uninstall on a bare environment and a virtual environment (from virtualenv 1.9.1). I'm running Ubuntu 12.04 LTS, Python 2.7.3, setuptools 0.6c11 (in the bare environment) and setuptools 0.7.4 (in virtualenv).

like image 110
Sarah Messer Avatar answered Oct 29 '22 17:10

Sarah Messer