2014-05-16 208 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