如何在Python 3中绘制模块依赖关系图?我找到了蛇食,但它似乎只适用于Python 2。
我假设您正在谈论的是snakefood,该文档在PyPI上可用,尽管自2009年以来未在此进行更新。由于它是旨在运行的应用程序,而不仅仅是旨在导入的模块库,即使目标是Python 3模块的目录,也可以使用Python 2.7执行它。它可以使用子进程从2.x或3.x运行。任何Python都可以很好地读取其输出文件。
我用hg clone --insecure <src> <dest>
克隆了它。我的初步实验表明,使用3.x运行它几乎不需要任何更改。我只需要在4个最大的文件中的2个中进行以下编译即可。
print x
=> print(x)
except XError, e:
=> except XError as e:
pydeps是当前标准。不幸的是,它绘制了所有模块的图形。如果要对软件包进行图形化处理,则需要像这样处理输出:
#!/usr/bin/env python
import csv
import re
import subprocess
packages = [
['cmm'],
['graph'],
['link', 'matching'],
['link'],
['model'],
['observation_learning'],
['problem'],
['pss'],
['rivalry'],
['sum_tensors'],
['target'],
['tensors'],
['fixed_point']]
def remove_module(p):
for suffix_str in ['iterated_function',
'exponential_family',
'fixed_point',
'graphed_element',
'graphed_trait',
'has_space',
'leaky_integral',
'color_stub',
'logging_stub',
'meta_parameters',
'newtons_method',
'observation_learning',
'plottable_trajectory',
'signal_curve_source',
'sum_tensors',
'fix_tree_repr']:
suffix = suffix_str.split('_')
if p[-len(suffix):] == suffix:
p[-len(suffix):] = [suffix_str]
if len(p) == 0:
assert False
return p
if len(p) <= 1:
return p
p = p[1:]
if p in packages:
return p
if len(p) > 1:
return p[: -1]
return ['cmm']
def shorten(name):
retval = '_'.join(remove_module(name.strip().split('_')))
if retval == 'graph':
return 'graph_'
return retval
def attrs(fmt):
return dict(kv.split('=') for kv in fmt.strip()[:-2].split(','))
def attrs2fmt(attrs):
return '[%s];' % ','.join('%s=%s' % (k, v) for k, v in attrs.items())
def main():
cp = subprocess.run(['pydeps', 'cmm', '--max-bacon=1', '--show-dot', '--no-output'],
stdout=subprocess.PIPE, text=True, check=True)
lines = cp.stdout.splitlines()
header = [line
for line in lines[:6]
if 'concentrate' not in line]
body = lines[6:-3]
nodes = [line for line in body if '->' not in line if line]
nodz = {}
for node in nodes:
name, fmt = node.split('[')
sname = shorten(name)
if sname in nodz:
continue
nodz[sname] = attrs(fmt)
rules = [line for line in body if '->' in line]
rulz = {}
used_nodes = set()
for rule in rules:
arrow, fmt = rule.split('[')
a, _, b = arrow.split()
a = shorten(a)
b = shorten(b)
if (a, b) in rulz:
continue
if a == b:
continue
if a == 'tensors':
continue
if b == 'cmm':
continue
rulz[(a, b)] = attrs(fmt)
used_nodes.add(a)
used_nodes.add(b)
with open('uml/cmm.dot', 'w') as fp:
fp.write('\n'.join(header))
for n in used_nodes:
a = nodz[n]
a['label'] = '"%s"' % n
print(' {} {}'.format(n, attrs2fmt(a)), file=fp)
for (a, b), fmt in rulz.items():
print(' {} -> {} {}'.format(a, b, attrs2fmt(fmt)), file=fp)
print('}', file=fp)
subprocess.run(['dot', '-Tpng', 'uml/cmm.dot', '-o', 'uml/cmm.png'])
if __name__ == "__main__":
main()