26

I have a file that I suspect was installed by pip. How can I find which package installed that file?

In other words, I'm looking for a command similar to pacman -Qo filename or dpkg -S filename, but for pip. Does it exist? Or should I use some combination of pip and grep? In that case, I don't know how to list all the file installed.

4

4 Answers 4

15

You could try with

pip list | tail -n +3 | cut -d" " -f1 | xargs pip show -f | grep "filename"

Then search through the results looking for that file.

5
  • Thanks, it almost works. But, for most of the packages I get Files: Cannot locate installed-files.txt is it an issue of my system?
    – DdD
    Commented Nov 2, 2015 at 18:19
  • 1
    @KraZmAzzD: I think pip list includes packages that weren't installed by pip itself, but by your system package manager. These will usually not include the installed-files.txt file.
    – Rörd
    Commented Nov 2, 2015 at 18:21
  • @Rörd grep may work, but it would need context (several lines up) to get the actual package name not just the file name.
    – JRD
    Commented Nov 2, 2015 at 18:23
  • 1
    For users of future pip versions: s/pip list/pip list --format=legacy/ if you get an error no such option: ----------------.
    – hoefling
    Commented Jan 19, 2018 at 13:46
  • Replace grep "filename" with grep -B10 "filename" to show some more metadata from the package in question (which or may or may not reflect the directory used in the Files section. Commented Aug 22, 2023 at 9:41
3

Since Python 3.8 standard library offers a more straightforward approach than Nathaniel 's:

import pathlib
import sys

if sys.version_info >= (3, 8):
    from importlib import metadata as importlib_metadata
else:
    import importlib_metadata


path_query_pattern = sys.argv[1]
for dist in importlib_metadata.distributions():
    paths = dist.files

    for file in dist.files:
        if pathlib.Path(file).match(path_query_pattern):
            print(dist.metadata["Name"] + ' --- "' + str(file) + '"')

The backport of the importlib_metadata for older python versions is available via pip.
Based on this answer.

Usage:

>>> python lookup_file.py pip.exe
pip --- "..\..\Scripts\pip.exe"

>>> python lookup_file.py Scripts\pip.exe
pip --- "..\..\Scripts\pip.exe"
2

You can use a python script like this:

#!/usr/bin/env python

import sys
try:
    from pip.utils import get_installed_distributions
except ModuleNotFoundError:
    from pip._internal.utils.misc import get_installed_distributions

MYPATH=sys.argv[1]
for dist in get_installed_distributions():
    # RECORDs should be part of .dist-info metadatas
    if dist.has_metadata('RECORD'):
        lines = dist.get_metadata_lines('RECORD')
        paths = [l.split(',')[0] for l in lines]
    # Otherwise use pip's log for .egg-info's
    elif dist.has_metadata('installed-files.txt'):
        paths = dist.get_metadata_lines('installed-files.txt')
    else:
        paths = []

    if MYPATH in paths:
        print(dist.project_name)

Usage looks like this:

$ python lookup_file.py requests/__init__.py 
requests

I wrote a more complete version here, with absolute paths:

https://github.com/nbeaver/pip_file_lookup

3
1

Try this!

find_pkg_by_filename(){ for pkg in $(pip list | cut -d" " -f1) ; do if pip show -f "$pkg" | grep "$1" ; then echo "=== Above files found in package $pkg ===" ; fi ; done ; }

find_pkg_by_filename somefilename

Note that if you add -q to the grep, it will exit as soon as there's a match, and then pip will complain about broken pipes.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.