2012-06-11 18 views
65

Bir uygulamanın nasıl çalıştığını öğrenmeye çalışıyorum. Ve bunun için her işlevin gövdesinin ilk satırı olarak hata ayıklama komutları ekliyorum, böylece günlük ismine bir mesaj gönderdiğim satırın numarasını (kod içinde) yanı sıra fonksiyonun ismini günlüğe kaydetme. Son olarak, bu uygulama birçok dosyadan oluştuğundan, uygulamanın kontrol akışını daha iyi anlayabilmek için tek bir kayıt dosyası oluşturmak istiyorum.Python Günlüğe kaydetme (işlev adı, dosya adı, satır numarası) tek bir dosya kullanarak

  1. fonksiyon adı almak için, ben function_name.__name__ kullanabilirsiniz ama ben hızla kopyalayıp bir jenerik Log.info("Message") yapıştırmak diye (FUNCTION_NAME kullanmak istemiyorsanız: Burada

    bildiğim budur tüm fonksiyonların gövdesi). Bunun __func__ makrosunu kullanarak yapıldığını biliyorum ancak python hakkında emin değilim. options = "LOG.debug('%(flag)s : %(flag_get)s' % locals()) ve ben gibi kullanarak denedim: başvurum Python locals() fonksiyonunu kullanıyor ama örneğin tamamen farkında değilim bir sözdiziminde
  2. dosya adını ve satır numarası almak için, bunu gördük (ve buna inanıyorum) LOG.info("My message %s" % locals()){'self': <__main__.Class_name object at 0x22f8cd0>} gibi bir şey üretir. Bu konuda herhangi bir girdi lütfen?

  3. Bir dosyaya oturum açmak için günlüğe kaydetmeyi ve işleyiciyi nasıl ekleyeceğinizi biliyorum, ancak tüm günlük iletilerini projedeki doğru işlev çağrıları sırasına kaydetmek için tek bir dosyanın kullanılıp kullanılamayacağını bilmiyorum.

Herhangi bir yardım için minnettar olurum.

Teşekkürler!

+0

pdb hata ayıklayıcısına 'import pdb; pdb.set_trace() 've daha sonra etkileşimli olarak kod aracılığıyla adım. Bu program akışını izlemenize yardımcı olabilir. –

+0

Harika bir fikir! Sağol Matt. Her seferinde hata ayıklamak zorunda kalmamak için soruda belirtildiği gibi bir günlük almak yararlı olacaktır. Ayrıca, Java için Eclipse (ctrl + tıklama fonksiyonu tanımına götürür) kadar iyi olan bir python için hata ayıklamayı kolaylaştırmak için kullanabileceğim bir IDE'yi biliyor musunuz? – user1126425

cevap

17

Burada birkaç marjinal ile ilgili sorularınız var.

En kolayıyla başlayacağım: (3). logging'u kullanarak, tüm çağrıları tek bir günlük dosyasına veya başka bir çıktı hedefine toplayabilirsiniz: bunlar işlem sırasında gerçekleştikleri sırada olacaktır.

Sonraki yukarı: (2). locals() geçerli kapsamın bir dict sağlar. Bu nedenle, başka bir argümanı olmayan bir yöntemde, geçerli örneğe bir başvuru içeren self kapsamınız vardır. Seni güldüren hile, % operatörünün RHS'si olarak bir dict kullanarak dize biçimlendirmesidir. "%(foo)s" % bar, bar["foo"]'un değeri ne olursa olsun değiştirilecektir.

Son olarak, fazla bilgiye giriş yapabilmek pdb tarafından kullanılan benzer bazı iç gözlem hileler, kullanabilirsiniz:

def autolog(message): 
    "Automatically log the current function details." 
    import inspect, logging 
    # Get the previous frame in the stack, otherwise it would 
    # be this function!!! 
    func = inspect.currentframe().f_back.f_code 
    # Dump the message + the name of this function to the log. 
    logging.debug("%s: %s in %s:%i" % (
     message, 
     func.co_name, 
     func.co_filename, 
     func.co_firstlineno 
    )) 

Bu geçirilen mesajını ve (orijinal) işlev adı, dosya adını günlüğe kaydeder tanımın göründüğü ve bu dosyadaki satır. Daha fazla bilgi için inspect - Inspect live objects'a bir göz atın.

Daha önce yaptığım yorumda da belirtildiği gibi,etkileşimli hata ayıklama istemine istediğiniz zaman import pdb; pdb.set_trace() satırını ekleyip programınızı yeniden çalıştırarak da bırakabilirsiniz. Bu, kodu seçerek, seçtiğiniz şekilde veri denetlemenizi sağlar.

logger.debug('your message') 

Örnek çıktı ben sağda çalıştığım bir komut dosyasından:

+0

Teşekkürler Matt! Bu autolog işlevini deneyeceğim. % Operatörünün RHS'si olarak kullanmayla ilgili biraz kafa karışıklığım var: ''% (foo) s:% (bar) s '' ayrıca 'bar [' foo '] 'nun değerini basar mı? Yoksa örneğinizden biraz farklı mı? – user1126425

+0

Temel olarak, "% () s" biçimindeki her şey, "" ile başvurulan nesnenin değeriyle değiştirilir. Http://docs.python.org/library/stdtypes.html#string-formatting –

+0

@synthesizerpatel'in yanıtının daha fazla örneği/detayı var. – Jan

276

bunun için doğru cevap sadece eklemek istediğiniz herhangi bir yere Sonra zaten sağlanan funcName değişken

import logging 
logger = logging.getLogger('root') 
FORMAT = "[%(filename)s:%(lineno)s - %(funcName)20s() ] %(message)s" 
logging.basicConfig(format=FORMAT) 
logger.setLevel(logging.DEBUG) 

kullanmaktır şimdi:

[invRegex.py:150 -   handleRange() ] ['[A-Z]'] 
[invRegex.py:155 -  handleRepetition() ] [[<__main__.CharacterRangeEmitter object at 0x10ba03050>, '{', '1', '}']] 
[invRegex.py:197 -   handleMacro() ] ['\\d'] 
[invRegex.py:155 -  handleRepetition() ] [[<__main__.CharacterRangeEmitter object at 0x10ba03950>, '{', '1', '}']] 
[invRegex.py:210 -  handleSequence() ] [[<__main__.GroupEmitter object at 0x10b9fedd0>, <__main__.GroupEmitter object at 0x10ba03ad0>]] 
+20

Bu cevap olmalıydı! – user3885927

+1

Harika .. Eklemek istediğimiz bir şey, log dosyasını dinamik olarak codefile olarak isimlendirebilir miyiz? Örneğin: logging.basicConfig (dosya adı = "% (dosya adı)", format = FORMAT) dosya adını dinamik olarak almak için denedim, ancak statik değer aldı. herhangi bir öneri? – Outlier

+2

@Outlier Hayır, bunu elde etmek için önerilen yol 'getLogger (__ isim __)' – farthVader

İlgili konular