我有大约700行代码。我必须写一些关于这段代码的文档。在本文档中,我计划有一个序列图来解释一下。像这样的东西:因为我有点懒,我想知道是否有工具从代码生成这个图。我不想失去整个周末这样做。
有些人有一个可以帮助我的想法吗?
感谢。
答案 0 :(得分:0)
我也在搜索此主题,发现以下有用信息: https://github.com/bereal/pyspy
它使用byteplay修补字节码,并且您可以添加自己的回调函数以在每次调用之前和之后进行某些操作。类似于使用sys.settrace
编写分析器,但更容易。
好吧,我添加了一些修复程序作为问题注释,因为我无法从此处正确使用git。您的函数可能会以文本形式编写DLS,就像PlantUML或ZenUML ...所需要的那样...并使用它来生成图表。
答案 1 :(得分:0)
Python中的Plantuml可能会有所帮助。有关如何安装使用链接 PlantUML with python
文本文件应如下所示:
Python -> HL : create
activate HL
HL -> LL : run
activate LL
LL -> SLI : exec
activate SLI
SLI --> LL
deactivate SLI
LL --> HL
deactivate LL
HL -> LL : push
activate LL
LL -> SLI : push
activate SLI
SLI --> LL
deactivate SLI
LL --> HL
deactivate LL
HL -> LL : run
activate LL
LL -> SLI : exec
activate SLI
SLI --> LL
deactivate SLI
LL --> HL
deactivate LL
HL -> LL : pop
activate LL
LL -> SLI : pop
activate SLI
SLI --> LL
deactivate SLI
LL --> HL
deactivate LL
HL --> Python
deactivate HL
为此可以通过python生成文本,例如,可以在方法声明之后添加。
print>>sd.txt, "->"+str(self.name)+":className"
这将附加到sd.txt中,并通过运行以下命令最终在项目目录中创建png文件:
python -m plantuml sd.txt
答案 2 :(得分:0)
这是一个简单的跟踪类,并提供了可以使用它的示例。 在要跟踪的每个函数的开头实例化该类。 装饰器也可以按照相同的原理完成,但是您必须相应地调整python框架解析
class SequenceOn:
autonumber = True
init_done = False
def __init__(self,participant=""):
if not SequenceOn.init_done :
#activate if requested only once
if SequenceOn.autonumber:
print ("autonumber")
SequenceOn.init_done = True
#retrieve callee frame
callee_frame = sys._getframe(1)
#method/function name
self.__funcName = callee_frame.f_code.co_name
# look for a class name
if 'self' in callee_frame.f_locals:
self.__className = callee_frame.f_locals['self'].__class__.__name__
else:
self.__className = participant
#retrieve the caller frame and class name of the caller
caller_frame = sys._getframe(2)
if 'self' in caller_frame.f_locals:
self.__caller = caller_frame.f_locals['self'].__class__.__name__
else:
self.__caller = ""
#print the plantuml message
activate = "++" if self.__caller != self.__className else ""
print (f'{self.__caller} -> {self.__className} {activate} :{self.__funcName}')
def __del__(self):
''' print the return message upon destruction '''
if self.__caller != self.__className:
print (f'{self.__caller} <-- {self.__className} -- ')
def note(self,msg):
print (f'note over {self.__className}:{msg}')
class SequenceOff:
''' empty class allowing to disable the trace by eg doing in the begining of a file:
Seq = SequenceOn # enable sequence generation
Seq = SequenceOff # disable sequence generation
and using seq for tracing instead of SequenceOn
'''
def __init__(self,participant=""):
pass
def __call__(self,msg):
pass
def note(self,msg):
pass
在下面的示例代码上:
if __name__ == "__main__":
class B:
def __init__(self):
pass
def funcB1(self):
s = SequenceOn()
def funcB2(self):
s = SequenceOn()
s.note("calling private method")
self.__funcB22()
def __funcB22(self):
s = SequenceOn()
class A:
def __init__(self):
pass
def funcA(self):
s = SequenceOn()
b = B()
b.funcB1()
b.funcB2()
# simple sequence
a = A()
a.funcA()
您得到:
autonumber
-> A ++ :funcA
A -> B ++ :funcB1
A <-- B --
A -> B ++ :funcB2
note over B:calling private method
B -> B :__funcB22
A <-- B --
<-- A --