Bir Python betiğinin profilini nasıl oluşturabilirsiniz?

Project Euler ve diğer kodlama yarışmaları genellikle maksimum çalışma süresine sahiptir veya insanlar kendi çözümlerinin ne kadar hızlı çalıştığıyla övünürler. Python'da bazen yaklaşımlar biraz karmaşıktır - örneğin, `main'e zamanlama kodu eklemek gibi.

Bir python programının çalışmasının ne kadar sürdüğünün profilini çıkarmanın iyi bir yolu nedir?

Çözüm

Python cProfile adında bir profil oluşturucu içerir. Yalnızca toplam çalışma süresini vermekle kalmaz, aynı zamanda her işlevi ayrı ayrı zamanlar ve her işlevin kaç kez çağrıldığını söyleyerek nerede optimizasyon yapmanız gerektiğini belirlemenizi kolaylaştırır.

Bunu kodunuzun içinden veya yorumlayıcıdan şu şekilde çağırabilirsiniz:

import cProfile
cProfile.run('foo()')

Daha da kullanışlı olarak, bir komut dosyasını çalıştırırken cProfil'i çağırabilirsiniz:

python -m cProfile myscript.py

Bunu daha da kolaylaştırmak için 'profile.bat' adında küçük bir toplu iş dosyası oluşturdum:

python -m cProfile %1

Yani tek yapmam gereken koşmak:

profile euler048.py

Ve bunu anlıyorum:

1007 function calls in 0.061 CPU seconds

Ordered by: standard name
ncalls  tottime  percall  cumtime  percall filename:lineno(function)
    1    0.000    0.000    0.061    0.061 :1()
 1000    0.051    0.000    0.051    0.000 euler048.py:2()
    1    0.005    0.005    0.061    0.061 euler048.py:2()
    1    0.000    0.000    0.061    0.061 {execfile}
    1    0.002    0.002    0.053    0.053 {map}
    1    0.000    0.000    0.000    0.000 {method 'disable' of '_lsprof.Profiler objects}
    1    0.000    0.000    0.000    0.000 {range}
    1    0.003    0.003    0.003    0.003 {sum}

DÜZENLEME: PyCon 2013'ten iyi bir video kaynağının bağlantısı güncellendi Python Profiling [Ayrıca YouTube üzerinden](https://www.youtube.com/watch?v=QJwVYlDzAXs).

Yorumlar (13)

Profilleyiciyi kullanmanın yalnızca ana iş parçacığında (varsayılan olarak) çalıştığını ve bunları kullanırsanız diğer iş parçacıklarından herhangi bir bilgi alamayacağınızı belirtmek gerekir. Bu durum profilleyici belgelerinde tamamen belirtilmediği için biraz sorun yaratabilir.

Ayrıca iş parçacıklarının profilini çıkarmak istiyorsanız, dokümanlardaki threading.setprofile() fonksiyonuna bakmak isteyeceksiniz.

Bunu yapmak için kendi threading.Thread alt sınıfınızı da oluşturabilirsiniz:

class ProfiledThread(threading.Thread):
    # Overrides threading.Thread.run()
    def run(self):
        profiler = cProfile.Profile()
        try:
            return profiler.runcall(threading.Thread.run, self)
        finally:
            profiler.dump_stats('myprofile-%d.profile' % (self.ident,))

ve standart sınıf yerine bu ProfiledThread sınıfını kullanın. Bu size daha fazla esneklik sağlayabilir, ancak özellikle sınıfınızı kullanmayacak üçüncü taraf kod kullanıyorsanız buna değeceğinden emin değilim.

Yorumlar (6)

Virtaal'ın kaynak'de profil oluşturmayı (belirli yöntemler/fonksiyonlar için bile) çok kolay hale getirebilecek çok kullanışlı bir sınıf ve dekoratör vardır. Çıktı daha sonra KCacheGrind'de çok rahat bir şekilde görüntülenebilir.

Yorumlar (1)