繁体   English   中英

pip两次安装软件包

[英]pip installs package twice

不幸的是,我无法复制它,但是我们已经看过几次了:

pip将一个软件包安装两次。

如果卸载第一个,则第二个可见,也可以卸载。

我的问题:如何使用python检查软件包是否已安装两次?

背景:我想编写一个检查此内容的测试(devOp)

更新

  • 软件包安装在virtualenv中。
  • 这两个软件包具有不同的版本。
  • 这不是手动解决问题的解决方案的重复。 我搜索解决方案以使用python代码检测到此问题。 如果我有问题,如何解决这个问题不重要。

更新2

命令pip freeze只输出一次软件包:

pip freeze | grep -i south
South==0.8.1

但是在virtual-env中它存在两次:

find lib -name top_level.txt |xargs cat | grep -i south
south
south

ls lib/python2.7/site-packages/| grep -i south
south
South-0.8.1-py2.7.egg
South-0.8.4-py2.7.egg-info

这应该工作:

def count_installs(pkg_name):
    import imp, sys
    n = 0
    for location in sys.path:
        try:
            imp.find_module(pkg_name, [location])
        except ImportError: pass
        else: n += 1
    return n

例如

>>> count_installs("numpy")
2
>>> count_installs("numpyd")
0
>>> count_installs("sympy")
1

我使用此方法检查软件包是否已安装两次:

def test_pip_python_packages_installed_twice(self):
    # https://stackoverflow.com/a/23941861/633961
    pkg_name_to_locations=defaultdict(set)
    for dist in pkg_resources.working_set:
        for pkg_name in dist._get_metadata('top_level.txt'):
            for location in sys.path:
                try:
                    importutils.does_module_exist_at_given_path(pkg_name, [location])
                except ImportError:
                    continue
                if location.startswith('/usr'):
                    # ignore packages from "root" level.
                    continue
                pkg_name_to_locations[pkg_name].add(location)

    errors=dict()
    for pkg_name, locations in sorted(pkg_name_to_locations.items()):
        if pkg_name in ['_markerlib', 'pkg_resources', 'site', 'easy_install', 'setuptools', 'pip']:
            continue
        if len(locations)==1:
            continue
        errors[pkg_name]=locations
    self.assertFalse(errors, 
                     'Some modules are installed twice:\n%s' % '\n'.join(['%s: %s' % (key, value) for key, value in sorted(errors.items())]))

importutils

def does_module_exist_at_given_path(module_name, path):
    '''
    imp.find_module() does not find zipped eggs.
    Needed for check: check if a package is installed twice.
    '''
    for path_item in path:
        result=None
        try:
            result=imp.find_module(module_name, [path_item])
        except ImportError:
            pass

        if result:
            return bool(result)
        if not os.path.isfile(path_item):
            continue
        # could be a zipped egg
        module=zipimport.zipimporter(path_item).find_module(module_name)
        if module:
            return bool(module)
    raise ImportError(module_name)

相关: imp.find_module()支持压缩鸡蛋

South-0.8.1-py2.7.egg是一个包含South源代码的zip存档, South-0.8.4-py2.7.egg-info是一个包含South库的元数据文件的目录。

对于每个pip安装的库,都存在.egg-info (对于从.tar.gz构建的库)或.dist-info (对于从wheel .whl安装的库)。

如果在元数据中将库标记为zip_safe (在setup.py setup(zip_safe=True) ,则创建.egg存档。 否则, pip将使用提取的python源文件创建目录。

很老版本的setuptools能够安装同一库的多个版本,并将其中一个标记为active ,但是如果我记得正确的话,提到的功能已在多年前删除。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM