Yalnızca hata ayıklamak için yazdırma ifadelerini kullanma


109

Python'da son zamanlarda çok kod yazıyorum. Ve daha önce hiç çalışmadığım verilerle, daha önce hiç görmediğim formülleri kullanarak ve devasa dosyalarla çalışıyorum. Tüm bunlar, her şeyin yolunda gidip gitmediğini doğrulamak ve başarısızlık noktalarını belirlemek için çok sayıda basılı ifade yazmamı sağladı. Ancak, genel olarak, bu kadar çok bilginin çıktısını almak iyi bir uygulama değildir. Yazdırma deyimlerini yalnızca hata ayıklamak ve yazdırılmasını istemediğimde atlanmalarına izin vermek istediğimde nasıl kullanabilirim?

Yanıtlar:


161

loggingModül isteyebileceği her şeye sahiptir. İlk başta aşırı görünebilir, ancak yalnızca ihtiyacınız olan parçaları kullanın. Ben kullanarak tavsiye ediyorum logging.basicConfigGünlük düzeyini değiştirmek için stderrve basit günlük yöntemleri , debug, info, warning, errorve critical.

import logging, sys
logging.basicConfig(stream=sys.stderr, level=logging.DEBUG)
logging.debug('A debug message!')
logging.info('We processed %d records', len(processed_records))

5
Ayrıca benim gibi bu modülü kurmakta sorun yaşamanız durumunda; günlük kaydı standart kitaplığın bir parçasıdır - sanal bir ortam kullanılırken bile pip kurulumuna gerek yoktur
Amr

Günlüğe kaydetme düzeyi yalnızca hataları yazdıracak ve iletileri hata ayıklamayacak şekilde nasıl ayarlanır?
Eduardo Pignatelli

@EduardoPignatelli seti level, içinde basicConfigçağrı için logging.ERROR.
Matt Joiner

Korkarım bu Jupyter laboratuvarı 1.2.6'da çalışmıyor. Günlük düzeyini bir kez ayarlayabilirsiniz ve kullanmanın yeniden ayarının logging.basicConfig(stream=sys.stderr, level=logging.ERROR)hiçbir etkisi olmayacaktır. Çekirdeği yeniden başlatmak ve yeni seviyeyi ayarlamak işe yarıyor, ancak bu benim için bir geçici çözüm.
Eduardo Pignatelli

@EduardoPignatelli bunun için başka bir soru sormalısınız. Ancak muhtemelen kök kaydedicideki seviyeyi doğrudan değiştirmeniz gerekecek, jupyter muhtemelen sizden önce basicConfig'i çağırıyor.
Matt Joiner

28

Bunu yapmanın basit bir yolu, bir günlük kaydı işlevini çağırmaktır:

DEBUG = True

def log(s):
    if DEBUG:
        print s

log("hello world")

Ardından, değerini değiştirebilir DEBUGve kodunuzu günlüğe kaydederek veya kaydetmeden çalıştırabilirsiniz.

Standart loggingmodül bunun için daha ayrıntılı bir mekanizmaya sahiptir.


5
Uzun vadede, verilen günlükleme modülünü kullanmak, kendinizinkini almaktansa (daha karmaşık görünse bile) muhtemelen daha iyidir .
mgiuca

11
Doğru, ama birinin kendi başına nasıl dönebileceğini anlamaya değer .
Greg Hewgill

1
Aslında. Yukarıdakiler nasıl loggingçalıştığına dair iyi bir fikirdir (çok basit bir seviyede).
mgiuca

Bu benim aws lambdalarım için kullandığım şey.
crsuarezf

21

Kullanım günlüğü yerleşik kütüphane modülü yerine baskı.

Bir Loggernesne yaratırsınız (diyelim logger) ve bundan sonra, bir hata ayıklama baskısı eklediğinizde, sadece şunu koyarsınız:

logger.debug("Some string")

logger.setLevelÇıkış seviyesini ayarlamak için programın başında kullanabilirsiniz . DEBUG olarak ayarlarsanız, tüm hata ayıklamaları yazdıracaktır. INFO veya daha yüksek bir değere ayarlayın ve hemen tüm hata ayıklamalar kaybolacaktır.

Ayrıca, farklı seviyelerde (BİLGİ, UYARI ve HATA) daha ciddi şeyleri kaydetmek için de kullanabilirsiniz.


12

İlk olarak, python'un kayıt çerçevesinin adaylığını ikinci olarak vereceğim . Bununla birlikte, nasıl kullandığınız konusunda biraz dikkatli olun. Özellikle: günlük çerçevesinin değişkenlerinizi genişletmesine izin verin, bunu kendiniz yapmayın. Örneğin, bunun yerine:

logging.debug("datastructure: %r" % complex_dict_structure)

yaptığınızdan emin olun:

logging.debug("datastructure: %r", complex_dict_structure)

çünkü benzer görünseler de, ilk sürüm devre dışı bırakılsa bile repr () maliyetine maruz kalır . İkinci versiyon bundan kaçınıyor. Benzer şekilde, kendinizinkini atarsanız, şöyle bir şey öneririm:

def debug_stdout(sfunc):
    print(sfunc())

debug = debug_stdout

aracılığıyla arandı:

debug(lambda: "datastructure: %r" % complex_dict_structure)

Bu, şunu yaparak devre dışı bırakırsanız, ek yükü önleyecektir:

def debug_noop(*args, **kwargs):
    pass

debug = debug_noop

Bu dizeleri hesaplamanın ek yükü, 1) hesaplaması pahalı olmadıkça veya 2) hata ayıklama deyimi, örneğin bir n ^ 3 döngüsünün veya başka bir şeyin ortasında olmadığı sürece önemli değildir. Bunun hakkında hiçbir şey bildiğimden değil.


Bu önemli konu hakkında daha fazla bilgi günlüğe kaydetme howto: docs.python.org/3/howto/logging.html#optimization
Martin CR

7

Başkalarını bilmiyorum, ancak bir "global sabit" ( DEBUG) ve ardından yalnızca eğer debug(msg)yazdıracak bir global işlevi ( ) tanımlamak için kullandım .msgDEBUG == True

Sonra hata ayıklama ifadelerimi şöyle yazıyorum:

debug('My value: %d' % value)

... sonra birim testini aldım ve bunu bir daha asla yapmadım! :)


Birim testi ha. Tamam, o zaman alınması gereken başka bir şey daha var :(
crazyaboutliv

1
Birim testinden vazgeçmek istemiyorum - bu çok önemlidir. Ancak bir hata ayıklama tekniği olarak bile bunun günlük tutmanın yerini alacağını düşünmüyorum. Bir şeyleri hızlıca test etmek için hala çok sayıda baskı yapıyorum.
mgiuca

@crazyaboutliv - Düzgün yapılan birim testi harika. Hızlı, özlü, takibi kolay bir sunum için python'a dalmanın bu bölümüne bir göz atın
mac

@mgiuca - Ben de hızlı baskı yapıyorum, ancak print()testi geçmek için kodumu gereken seviyeye getirmek için sadece bir kaç tane var . Asla print()her yerde büyük miktarda bulmam. Günlük kaydı da harika! :)
mac

2
@mac Görünüşe göre bağlantınız artık açık bir 'www' gerektiriyor - artık burada barındırılıyor .
culix
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.