可以从python代码生成序列图吗?

时间:2017-07-21 12:58:43

标签: python sequence-diagram

我有大约700行代码。我必须写一些关于这段代码的文档。在本文档中,我计划有一个序列图来解释一下。像这样的东西:enter image description here因为我有点懒,我想知道是否有工具从代码生成这个图。我不想失去整个周末这样做。

有些人有一个可以帮助我的想法吗?

感谢。

3 个答案:

答案 0 :(得分:0)

我也在搜索此主题,发现以下有用信息: https://github.com/bereal/pyspy

它使用byteplay修补字节码,并且您可以添加自己的回调函数以在每次调用之前和之后进行某些操作。类似于使用sys.settrace编写分析器,但更容易。

好吧,我添加了一些修复程序作为问题注释,因为我无法从此处正确使用git。您的函数可能会以文本形式编写DLS,就像PlantUMLZenUML ...所需要的那样...并使用它来生成图表。

答案 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

enter image description here

为此可以通过python生成文本,例如,可以在方法声明之后添加。

print>>sd.txt, "->"+str(self.name)+":className"

这将附加到sd.txt中,并通过运行以下命令最终在项目目录中创建png文件:

python -m plantuml sd.txt

python-UML-sequence-diagram

答案 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 --

哪个生成: enter image description here