pip freeze: 仅显示通过pip安装的软件包

8
我想知道哪些Python包是通过pip安装的,哪些是通过rpm安装的。
我在任何虚拟环境中运行,并想知道是否有一些包是通过pip安装的。
背景:我们的政策是在“根级别”使用RPM。我想找到违反该政策的地方。

你的情况是,你有多个虚拟环境,并且你想要从根级别检查通过pip安装的软件包吗? - Laszlowaty
如果pip list返回所有已安装软件包的列表,则可以使用rpm -qa查找通过rpm安装的软件包,两者之间的差异将是不符合您策略的软件包。以上方法适用于您吗? - Jacques Gaudin
我猜这两个名称并不总是完全相同(逐字节),而只是相似的(对于人类大脑来说看起来相等)。一个例子:pip freeze 告诉它“python-dateutil”,RPM 名称也是相同的。pip freeze 告诉我“Pillow”,但 RPM 中它被称为 python-Pillow... - guettli
一般来说,我认为这是不可能的。你可以检查 $HOME/.cache/pip 或类似的根目录,但这不能保护你免受 pip install x-1.2.3; apt-get install python-x-1.2.3 这样的序列攻击。 - Dima Tisnek
您的用户是否具有sudo/root访问权限? - Luke Exton
2个回答

2
假设:
  • 我不确定红帽系统,但对于debian / ubuntu。
  • 我假设您正在使用系统Python。
  • 我认为这并不重要,但您可能需要检查pip install --user <package_name>以进行本地用户包安装。

在debian系统上,默认情况下安装的软件包会被安装在:

/usr/lib/python2.7/dist-packages/

而pip安装的软件包会安装在以下位置:

/usr/bin/local/python2.7/dist-packages

要查看所有安装路径,您可以在Python shell中运行以下命令:
import site; site.getsitepackages()
['/usr/local/lib/python2.7/dist-packages', '/usr/lib/python2.7/dist-packages']

根据pip freeze文档-l将显示任何本地安装的软件包(即非全局软件包)。但是,您需要在正确的环境中。
pip freeze -l

如果使用Virtualenvs:它们将使用site-packages目录。
locate -r '/site-packages$'

请注意,安装到不同目录的任何软件包都不能通过这种方法进行定位:如何使用pip将Python软件包安装到不同的目录? 最后的技巧是,使用pip show检查确切的安装路径。从pip中获取名称,将其传递到pip show并过滤输出以获取名称->位置映射。
pip freeze | awk '{split($0,a,"="); print a[1]}' | xargs -P 5 -I {} pip show {} | grep 'Name\|Location'

1
“pip freeze -l” 对我来说是新的。我查看了在虚拟环境中使用带有 -l 和不带 -l 参数时的区别。可以很好地检测虚拟环境内外的差异,但它并不能帮助我们决定是从 RPM 还是从 pip 安装的。 - guettli
在您的设置中,rpm安装位置与pip安装位置是否不同?例如/usr/lib//usr/bin/local/,还是相同的? - Luke Exton
1
不,抱歉。它安装在相同的位置:/usr/lib/python2.7/site-packages/ - guettli
我已经添加了一行代码,希望能够帮助确定确切的安装路径。需要注意的是,许多这些安装包都是默认安装在系统上的,甚至没有通过rpm安装。 - Luke Exton

2
如何稍微转变一下问题,只检查哪些属于rpm,哪些不属于rpm。请尝试以下命令:
import os, sys, subprocess, glob

def type_printed(pth, rpm_dirs=False):

    if not os.path.exists(pth):
        print(pth + ' -- does not exist')
        return True        
    FNULL = open(os.devnull, 'w')
    if rpm_dirs or not os.path.isdir(pth):
        rc = subprocess.call(['rpm', '-qf', pth], stdout=FNULL, stderr=subprocess.STDOUT) 
        if rc == 0:
            print(pth + ' -- IS RPM')
            return True 
        print(pth + ' -- NOT an RPM')
        return True 
    return False 


for pth in sys.path:
    if type_printed(pth):
        continue 
    contents = glob.glob(pth + '/*') 
    for subpth in contents:
        if type_printed(subpth, rpm_dirs=True):
            continue
        print(subpth + ' -- nothing could be determined for sure')

并将输出通过类似于以下内容的管道进行处理:

grep -e '-- NOT' -e '-- nothing could be determined'

好的,这样我就可以找到以root身份通过pip安装的东西了。我喜欢pip,但只在虚拟环境中使用 :-) - guettli

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接