Arama Grafiği Çizme


12

Python ile yazılmış eski bir kod tabanı koruyorum. Özellikle, bir modülden diğer modülleri diğer fonksiyonları çağıran diğer fonksiyonları çağıran karmaşık bir kod parçası vardır. OOP değil, sadece fonksiyonlar ve modüller.
Ana işlevi çağırdığımda akışın başladığı ve bittiği yeri takip etmeye çalıştım ama alt çizimlerde kaybolmaya çalıştığım için bunu çizmem gerektiğini hissediyorum.

Beni ilgilendiren, her işlevin, görevlerini tamamlamak ve değeri arayana geri döndürmek için vücutlarında birden çok dış işlevi çağırmasıdır.

Bunu nasıl çizebilirim? Bu tür davranışları / kodları belgelemek için ne tür bir grafik / grafik uygun olur?

Dolayısıyla, ne bir akış şeması ne de UML diyagramı çizmenin yararlı olacağını düşünmüyorum. Bir çağrı grafiği, belki?


doxygen - çağrı / arayan grafikleri üretecek, python için ne kadar desteğe sahip olduğundan emin değilim. Bunun için python kodunu belgeleyebileceğinizi biliyorum.
gbjbaanb

Pycallgraph'ı denedim ama kullanmak için çok karmaşık / çok derin. Bu benim kod karmaşıklığı nedeniyle düz python django ve API url harici çağrı ile karıştırır. Bu yüzden sadece ihtiyacım olan ilgili kısmı dikkate alarak elle çizmek istedim. Sorun, sistemi tam olarak anlamak için ne tür bir grafik kullanacağımı bilmemem
Leonardo

5
Eğer bu sadece anlamanıza yardımcı olmaksa, doğal olarak gelen her şeyi çizin. Resmi belgelere giderse, daha sonra istediğiniz zaman düzenleyebilirsiniz.
jonrsharpe

Yanıtlar:


9

Burada aradığınızın bir Dizi Diyagramı olduğunu düşünüyorum . Bunlar, çeşitli modüllerin okları kullanarak birbirlerini arama sırasını görselleştirmenizi sağlar.

Birini inşa etmek basittir:

  1. Başlangıç ​​sınıfınızı altında noktalı bir çizgi ile çizin.
  2. Arama izlemesindeki bir sonraki sınıfı / yöntemi, bunun altında noktalı bir çizgi ile çizin
  3. Çizgileri, çizdiğiniz son okun altına dikey olarak konumlandırılmış bir okla bağlayın
  4. İzinizdeki tüm aramalar için 2-3. Adımları tekrarlayın

Misal

Diyelim ki aşağıdaki kod için bir dizi diyagramı oluşturmak istiyoruz:

def long_division(quotient, divisor):
    solution = ""
    remainder = quotient
    working = ""
    while len(remainder) > 0:
        working += remainder[0]
        remainder = remainder[1:]
        multiplier = find_largest_fit(working, divisor)
        solution += multiplier
        working = calculate_remainder(working, multiplier, divisor)
    print solution


def calculate_remainder(working, multiplier, divisor):
    cur_len = len(working)
    int_rem = int(working) - (int(multiplier) * int (divisor))
    return "%*d" % (cur_len, int_rem)


def find_largest_fit(quotient, divisor):
    if int(divisor) == 0:
        return "0"
    i = 0
    while i <= 10:
        if (int(divisor) * i) > int(quotient):
            return str(i - 1)
        else:
            i += 1


if __name__ == "__main__":
    long_division("645", "5")

Çizeceğimiz ilk şey main, yönteme bağlanan giriş noktası ( ) long_division. Bunun, yöntem çağrısının kapsamını belirten long_division'da bir kutu oluşturduğunu unutmayın. Bu basit örnek için, kutu, çalıştırılan tek şey olması nedeniyle dizi şemamızın tüm yüksekliği olacaktır.

resim açıklamasını buraya girin

Şimdi find_largest_fitçalışma numaramıza uyan ve bize geri dönen en büyük katıyı bulmaya çağırıyoruz . Biz bir çizgi çizmek long_divisioniçin find_largest_fitişlev çağrısı için kapsamını belirtmek için başka bir kutu ile. Çarpan döndürüldüğünde kutunun nasıl bittiğine dikkat edin; bu fonksiyonların kapsamının sonu!

resim açıklamasını buraya girin

Daha büyük bir sayı için birkaç kez tekrarlayın ve grafiğiniz aşağıdaki gibi görünmelidir:

resim açıklamasını buraya girin

notlar

Çağrıları değişken adları geçirilmiş olarak mı yoksa yalnızca belirli bir vakayı belgelemek istiyorsanız değerleriyle mi etiketlemek istediğinizi seçebilirsiniz. Kendini çağıran bir işlevle özyineleme de gösterebilirsiniz.

Ayrıca, kullanıcıları burada gösterebilir ve onlara bilgi verebilir ve sisteme girdilerini yeterince kolayca gösterebilirsiniz. Oldukça esnek bir sistem olduğunu düşünüyorum.


Teşekkürler, dizi diyagramını biliyorum, ama bana göre oop için daha uygun geliyor. Benim durumumda işler biraz daha dağınık, yani birden fazla modüle yayılmış yaklaşık 20 fonksiyon / yardımcıya sahibim. Ho işlevin ait olduğu modülü belirtir miyim? İthalat sırasında bazı işlevlerin de yeniden adlandırıldığı göz önünde bulundurulduğunda ..
Leonardo

1
Ben kaç modül var önemli değil söyleyebilirim - yukarıdaki örnek ya da hiç de değil. Onları daha sonra bulabilmeniz için adlandırın, ModuleA / function1, ModuleB / Function2 vb. 20 işlev için daha büyük olacaktır, ancak kesinlikle anlaşılması imkansız değildir. Yapabileceğiniz bir diğer düşünce, bir fonksiyonun son kullanımından sonra çizgiyi sonlandırmak ve diyagramınızda yatay alan kazanmak için altına başka bir fonksiyon satırı koymaktır.
Ampt

7

Bence bir çağrı grafiği en uygun görselleştirme olurdu. Elle yapmamaya karar verirseniz pyan, bir python dosyasında statik analiz yapan ve bir grafikviziti dosyası (bir görüntüye dönüştürülebilir) aracılığıyla görselleştirilmiş bir çağrı grafiği oluşturabilen güzel bir küçük araç vardır . Birkaç çatal var, ancak en tam özellikli olanı https://github.com/davidfraser/pyan gibi görünüyor .

Komutu çalıştırdığınızda işlenmesini istediğiniz tüm dosyaları belirtmeniz yeterlidir:

python ~/bin/pyan.py --dot a.py b.py c.py -n > pyan.dot; dot -Tpng -opyan.png pyan.dot

veya

python ~/bin/pyan.py --dot $(find . -name '*.py') -n > pyan.dot; dot -Tpng -opyan.png pyan.dot

Bir fonksiyonun nerede tanımlandığını gösteren çizgileri kaldıran '-n' ile grafiği daha temiz yapabilirsiniz.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.