How do I find the location of my Python site-packages directory?

Viewed 1365060

How do I find the location of my site-packages directory?

22 Answers

A solution that:

  • outside of virtualenv - provides the path of global site-packages,
  • insidue a virtualenv - provides the virtualenv's site-packages

...is this one-liner:

python -c "from distutils.sysconfig import get_python_lib; print(get_python_lib())"

Formatted for readability (rather than use as a one-liner), that looks like the following:

from distutils.sysconfig import get_python_lib
print(get_python_lib())


Source: an very old version of "How to Install Django" documentation (though this is useful to more than just Django installation)

For Ubuntu,

python -c "from distutils.sysconfig import get_python_lib; print get_python_lib()"

...is not correct.

It will point you to /usr/lib/pythonX.X/dist-packages

This folder only contains packages your operating system has automatically installed for programs to run.

On ubuntu, the site-packages folder that contains packages installed via setup_tools\easy_install\pip will be in /usr/local/lib/pythonX.X/dist-packages

The second folder is probably the more useful one if the use case is related to installation or reading source code.

If you do not use Ubuntu, you are probably safe copy-pasting the first code box into the terminal.

A modern stdlib way is using sysconfig module, available in version 2.7 and 3.2+. Unlike the current accepted answer, this method still works regardless of whether or not you have a virtual environment active.

Note: sysconfig (source) is not to be confused with the distutils.sysconfig submodule (source) mentioned in several other answers here. The latter is an entirely different module and it's lacking the get_paths function discussed below. Additionally, distutils is deprecated in 3.10 and will be unavailable soon.

Python currently uses eight paths (docs):

  • stdlib: directory containing the standard Python library files that are not platform-specific.
  • platstdlib: directory containing the standard Python library files that are platform-specific.
  • platlib: directory for site-specific, platform-specific files.
  • purelib: directory for site-specific, non-platform-specific files.
  • include: directory for non-platform-specific header files.
  • platinclude: directory for platform-specific header files.
  • scripts: directory for script files.
  • data: directory for data files.

In most cases, users finding this question would be interested in the 'purelib' path (in some cases, you might be interested in 'platlib' too). The purelib path is where ordinary Python packages will be installed by tools like pip.

At system level, you'll see something like this:

# Linux
$ python3 -c "import sysconfig; print(sysconfig.get_path('purelib'))"
/usr/local/lib/python3.8/site-packages

# macOS (brew installed python3.8)
$ python3 -c "import sysconfig; print(sysconfig.get_path('purelib'))"
/usr/local/Cellar/python@3.8/3.8.3/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages

# Windows
C:\> py -c "import sysconfig; print(sysconfig.get_path('purelib'))"
C:\Users\wim\AppData\Local\Programs\Python\Python38\Lib\site-packages

With a venv, you'll get something like this

# Linux
/tmp/.venv/lib/python3.8/site-packages

# macOS
/private/tmp/.venv/lib/python3.8/site-packages

# Windows
C:\Users\wim\AppData\Local\Temp\.venv\Lib\site-packages

The function sysconfig.get_paths() returns a dict of all of the relevant installation paths, example on Linux:

>>> import sysconfig
>>> sysconfig.get_paths()
{'stdlib': '/usr/local/lib/python3.8',
 'platstdlib': '/usr/local/lib/python3.8',
 'purelib': '/usr/local/lib/python3.8/site-packages',
 'platlib': '/usr/local/lib/python3.8/site-packages',
 'include': '/usr/local/include/python3.8',
 'platinclude': '/usr/local/include/python3.8',
 'scripts': '/usr/local/bin',
 'data': '/usr/local'}

A shell script is also available to display these details, which you can invoke by executing sysconfig as a module:

python -m sysconfig

Addendum: What about Debian / Ubuntu?

As some commenters point out, the sysconfig results for Debian systems (and Ubuntu, as a derivative) are not accurate. When a user pip installs a package it will go into dist-packages not site-packages, as per Debian policies on Python packaging.

The root cause of the discrepancy is because Debian patch the distutils install layout, to correctly reflect their changes to the site, but they fail to patch the sysconfig module.

For example, on Ubuntu 20.04.4 LTS (Focal Fossa):

root@cb5e85f17c7f:/# python3 -m sysconfig | grep packages
    platlib = "/usr/lib/python3.8/site-packages"
    purelib = "/usr/lib/python3.8/site-packages"

root@cb5e85f17c7f:/# python3 -m site | grep packages
    '/usr/local/lib/python3.8/dist-packages',
    '/usr/lib/python3/dist-packages',
USER_SITE: '/root/.local/lib/python3.8/site-packages' (doesn't exist)

It looks like the patched Python installation that Debian/Ubuntu are distributing is a bit hacked up, and they will need to figure out a new plan for 3.12+ when distutils is completely unavailable. Probably, they will have to start patching sysconfig as well, since this is what pip will be using for install locations.

As others have noted, distutils.sysconfig has the relevant settings:

import distutils.sysconfig
print distutils.sysconfig.get_python_lib()

...though the default site.py does something a bit more crude, paraphrased below:

import sys, os
print os.sep.join([sys.prefix, 'lib', 'python' + sys.version[:3], 'site-packages'])

(it also adds ${sys.prefix}/lib/site-python and adds both paths for sys.exec_prefix as well, should that constant be different).

That said, what's the context? You shouldn't be messing with your site-packages directly; setuptools/distutils will work for installation, and your program may be running in a virtualenv where your pythonpath is completely user-local, so it shouldn't assume use of the system site-packages directly either.

pip show will give all the details about a package: https://pip.pypa.io/en/stable/reference/pip_show/ [pip show][1]

To get the location:

pip show <package_name>| grep Location

In Linux, you can go to site-packages folder by:

cd $(python -c "import site; print(site.getsitepackages()[0])")

This works for me. It will get you both dist-packages and site-packages folders. If the folder is not on Python's path, it won't be doing you much good anyway.

import sys; 
print [f for f in sys.path if f.endswith('packages')]

Output (Ubuntu installation):

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

An additional note to the get_python_lib function mentioned already: on some platforms different directories are used for platform specific modules (eg: modules that require compilation). If you pass plat_specific=True to the function you get the site packages for platform specific packages.

from distutils.sysconfig import get_python_lib
print get_python_lib()

You should try this command to determine pip's install location

Python 2

pip show six | grep "Location:" | cut -d " " -f2

Python 3

pip3 show six | grep "Location:" | cut -d " " -f2

For those who are using poetry, you can find your virtual environment path with poetry debug:

$ poetry debug

Poetry
Version: 1.1.4
Python:  3.8.2

Virtualenv
Python:         3.8.2
Implementation: CPython
Path:           /Users/cglacet/.pyenv/versions/3.8.2/envs/my-virtualenv
Valid:          True

System
Platform: darwin
OS:       posix
Python:   /Users/cglacet/.pyenv/versions/3.8.2

Using this information you can list site packages:

ls /Users/cglacet/.pyenv/versions/3.8.2/envs/my-virtualenv/lib/python3.8/site-packages/

I made a really simple function that gets the job done

import site


def get_site_packages_dir():
        return [p for p  in site.getsitepackages()
                if p.endswith(("site-packages", "dist-packages"))][0]

get_site_packages_dir()
# '/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages'

If you want to retrieve the results using the terminal:

python3 -c "import site;print([p for p in site.getsitepackages() if p.endswith(('site-packages', 'dist-packages')) ][0])"

/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages


Something that has not been mentioned which I believe is useful, if you have two versions of Python installed e.g. both 3.8 and 3.5 there might be two folders called site-packages on your machine. In that case you can specify the python version by using the following:

py -3.5 -c "import site; print(site.getsitepackages()[1])
Related