【问题标题】:pip installs package twicepip 安装包两次
【发布时间】:2014-07-05 00:54:03
【问题描述】:

很遗憾我无法重现它,但我们已经看过好几次了:

pip 安装一个包两次。

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

我的问题:如果一个包被安装了两次,我如何用 python 检查?

背景:我想写一个测试来检查这个(devOp)

更新

  • 软件包安装在 virtualenv 中。
  • 这两个包有不同的版本。
  • 这不是手动解决此问题的解决方案的副本。我搜索了一个解决方案来用 python 代码检测这个。如何解决这个问题不是我的问题。

更新 2

命令pip freeze只输出一次包:

pip freeze | grep -i south
South==0.8.1

但在虚拟环境中它存在两次:

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

【问题讨论】:

  • 这个问题可能会对您有所帮助:stackoverflow.com/questions/11166014/…
  • 它们是不同的版本吗?一个是全局安装的,一个是安装在你的 virtualenv 中的吗?
  • @guettli 真是可惜,不能复现。

标签: python package pip virtualenv


【解决方案1】:

这应该可行:

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

【讨论】:

  • 这行得通。非常感谢。 A 编写了一个单元测试,它遍历工作集中的所有包。见下文。
【解决方案2】:

我使用这种方法来检查一个包是否安装了两次:

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())]))

导入工具

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() which supports zipped eggs

【讨论】:

    【解决方案3】:

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

    .egg-info(用于从.tar.gz 构建的库)或.dist-info(用于从轮子.whl 安装的库)存在于pip 安装的每个库中。

    如果库在元数据中标记为zip_safesetup(zip_safe=True)setup.py)中,则创建.egg 存档。 否则 pip 会创建一个包含提取的 Python 源文件的目录。

    非常旧版本的 setuptools 能够安装同一个库的多个版本并将其中一个标记为 active,但如果我在多年前删除了提到的功能正确回忆。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-02-27
      • 1970-01-01
      • 2013-12-03
      • 2021-04-14
      • 2016-02-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多