我需要构建一个由requirements.txt文件中指定的Python分发列表提供的模块列表。首先安装这些发行版,以便在本地进行检查。
看起来我应该能够使用pip.req.parse_requirements
从需求文件中获取分发列表。从那里,我如何找到分发提供的模块的名称?
答案 0 :(得分:3)
如果你的python版本是2.3 +
,你可以使用内置的pkgutil模块例如,
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
答案 1 :(得分:2)
因为,就像你说的那样,发行版不是它们包含的模块,我们遇到了一个问题:发行版的典型安装过程 - 即afaik,包的集合以及安装程序 - 是下载,解压缩,然后运行setup.py,它处理安装过程的其余部分。
结果是,即使给出了Python发行版,你实际上无法告诉setup.py在没有运行它的情况下会做什么。可能存在约定,您可以提取大量信息并制定很多好的猜测,但运行“setup.py”文件实际上是查看它实际安装到站点包中的唯一方法。因此,parse_requirements
或者任何pip内部实际上对你没有用,除非你只对发行版感兴趣。
所以,话虽如此,我认为管理问题的最佳方法是:
pip -r requirements.txt
实际安装所有软件包sys.path
,查找.py,.pyc以及__init__.py?
个文件的子文件夹,以构建模块列表。第三步可能是其他更好的方式,我不确定。此外,您仍然存在丢失动态创建的模块或其他技巧的风险,但这应该捕获大多数模块。
修改强>
这里的一些代码应该适用于除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:
嗯,老鼠。 GWW有正确的想法。比我的解决方案要好得多。