<p>正如您所说,由于发行版不是它们包含的模块,所以我们遇到了一个问题:发行版的典型安装过程是下载、解包,然后运行设置.py,它处理安装过程的其余部分。在</p>
<p>结果是,即使给定了Python发行版,您也不能真正知道是什么设置.py不用运行也行。可能会有一些惯例,你可能会从中找出很多信息,做出很多好的猜测,但是运行这些设置.py'文件实际上是查看它实际安装到站点包中的内容的唯一方法。因此,<code>parse_requirements</code>,或者实际上任何pip内部构件都不会对您有用,除非您只对发行版感兴趣。在</p>
<p>因此,尽管如此,我认为解决问题的最佳方法是:</p>
<ol>
<li>设置不带站点包的虚拟环境</li>
<li><code>pip -r requirements.txt</code>来实际安装所有包</li>
<li>在<code>sys.path</code>中搜索.py、.pyc并放入<code>__init__.py?</code>文件的子文件夹中,以构建模块列表。在</li>
<li>杀了那个虚拟人然后继续前进。在</li>
</ol>
<p>我不确定第三步在其他更好的方面是否可行。此外,您仍然有可能丢失动态创建的模块或其他棘手的问题,但这应该会捕获大部分模块。在</p>
<p><strong>编辑:</strong></p>
<p>这里有一些代码应该适用于除zip文件以外的所有文件:</p>
<pre><code>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
</code></pre>
<p><strong>编辑2:</strong></p>
<p>好吧,克里基。GWW有正确的想法。比我的好得多的解决办法。在</p>