2014-05-16 47 views
1

不幸的是我不能复制,但我们已经看到了好几次:PIP封装安装两次

PIP安装了一个包的两倍。

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

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

背景:我想写来做这个(devOp)测试

更新

  • 软件包安装在一个virtualenv中。
  • 这两个软件包有不同的版本。
  • 这不是手工解决这个问题的解决方案的重复。我搜索一个解决方案来检测这个python代码。如何解决这个问题不属于我的问题。

更新2

命令pip freeze输出包只有一次:

pip freeze | grep -i south 
South==0.8.1 

但在虚拟-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 
+0

这个问题可以帮助你与这样的:HTTP ://stackoverflow.com/questions/11166014/how-to-tell-if-you-have-multiple-djangos-installed – Ryan

+2

他们是不同的版本?是一个安装globablly和一个安装在你的virtualenv? – dm03514

+1

@guettli真的很可惜,你不能重现它。 –

回答

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

0

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

.egg-info(从.tar.gz建库)或.dist-info(从车轮.whl安装库)都存在由pip安装在每台库。

.egg如果元数据库中标记为zip_safe的库(setup(zip_safe=True)setup.py),则会创建归档。 否则pip用提取的python源文件生成一个目录。

很老的setuptools的版本能够安装同一个库的几个版本,并标记其中之一作为活跃,但如果我没有记错提到的功能是前下降了好几年了。

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 
+0

这工作。非常感谢你。写了一个unittest循环遍历工作集中的所有包。见下文。 – guettli