2012-01-06 57 views
4

我需要構造通過在requirements.txt文件中指定的Python發行的列表中提供的模塊的列表。這些發行版將首先安裝,以便它們可以在當地查看。如何找到給定的Python發行版提供的模塊?

它看起來像我應該能夠使用pip.req.parse_requirements獲得從需求文件分發列表。從那裏,我如何找到發行版提供的模塊的名稱?

+0

你不利的運行python腳本,每個分配? – GWW 2012-01-09 03:46:18

+0

@GWW我不太清楚你的意思,但我真的沒有任何選擇不利。 – 2012-01-09 13:26:37

+0

我不明白你的問題,如果你有requirements.txt那麼那些是模塊,你到底在找什麼?事實上,如果他們將被安裝和檢查,那麼你將使用requirements.txt的內容來做到這一點。 – 2012-01-09 14:32:34

回答

3

你或許可以使用內置的pkgutil模塊,如果你的Python版本2.3+

例如,

import sys, pkgutil 
mods = set() 

#You may not need this part if you don't care about the builtin modules 
print sys.builtin_module_names 
for m in sys.builtin_module_names: 
    if m != '__main__': 
     mods.add(m) 
     #mods.add(m) 


for loader, name, ispkg in pkgutil.walk_packages(): 
    if name.find('.') == -1: 
     mods.add(name) 

print mods 
2

因爲,就像你說的,分佈是不是它們所包含的模塊,我們碰到一個問題:典型的分佈安裝過程 - 這是,據我所知,包使用安裝程序一起的集合 - 是下載,解包,然後運行setup.py,它處理安裝過程的其餘部分。

其結果是,即使給出一個Python分佈,你不能真正告訴什麼setup.py將在不運行它做。可能會有一些約定,你可能能夠提取大量信息並制定很多好的猜測,但運行該「setup.py」文件是真正能夠看到它實際安裝到網站包中的唯一方法。因此,parse_requirements,或者真的任何點組件內部真的不會對你有用,除非你只對分配感興趣。

所以,他這樣說,我認爲管理問題的最佳辦法是:

  1. 建立一個虛擬環境中的w/o現場包
  2. pip -r requirements.txt實際安裝所有的軟件包
  3. 拖網通過sys.path,尋找的.py,.pyc文件和子文件夾將用於__init__.py?文件來構建模塊的列表。
  4. 殺了那的virtualenv和對你的方式移動。

第三步可能是其他更好的方法,我不確定。此外,您仍然冒着缺少動態創建的模塊或其他技巧的風險,但這應該捕獲大部分模塊。

編輯:

下面是一些代碼,應爲一切工作,但zip文件:

import sys, os 

def walk_modules_os(root): 
    def inner_walk(dir_path, mod_path): 
     filelist = os.listdir(dir_path) 
     pyfiles = set() 
     dirs = [] 
     for name in filelist: 
      if os.path.isdir(os.path.join(dir_path, name)): 
       dirs.append(name) 
      else: 
       pre, ext = os.path.splitext(name) 
       if ext in ('.py', '.pyc', '.pyo'): 
        pyfiles.add(pre) 

     if len(mod_path): 
      if '__init__' not in pyfiles: 
       return 
      pyfiles.remove('__init__') 
      yield mod_path 

     for pyfile in pyfiles: 
      yield mod_path + (pyfile,) 

     for directory in dirs: 
      sub = os.path.join(dir_path, directory) 
      for mod in inner_walk(sub, mod_path + (directory,)): 
       yield mod 

    root = os.path.realpath(root) 
    if not os.path.isdir(root): 
     return iter([]) 
    return iter(inner_walk(root, tuple())) 

# you could collect as a set of tuples and do set subtraction, too 
for path in sys.path: 
    for mod in walk_modules_os(path): 
     print mod 

編輯2:

嘛,crikey。 GWW有正確的想法。比我的更好的解決方案。

+0

我認爲這幾乎是我要去的路線。 1.查找當前可用的模塊。 2.安裝所需的軟件包3.在安裝新軟件包後查找可用的模塊。 – 2012-01-10 13:24:47

相關問題