Yanıtlar:
Geçerli özel durumu bir mesajla birlikte gelen izleme bilgileriyle birlikte günlüğe kaydetmek logging.exception
için except:
işleyici / blok içinden kullanın .
import logging
LOG_FILENAME = '/tmp/logging_example.out'
logging.basicConfig(filename=LOG_FILENAME, level=logging.DEBUG)
logging.debug('This message should go to the log file')
try:
run_my_stuff()
except:
logging.exception('Got exception on main handler')
raise
Şimdi günlük dosyasına bakalım /tmp/logging_example.out
:
DEBUG:root:This message should go to the log file
ERROR:root:Got exception on main handler
Traceback (most recent call last):
File "/tmp/teste.py", line 9, in <module>
run_my_stuff()
NameError: name 'run_my_stuff' is not defined
logger = logging.getLogger('yourlogger')
için yazmak logger.exception('...')
zorundasınız ...
Kullanım exc_info
seçenekleri daha iyi olabilir, uyarı veya hata başlığı kalır:
try:
# coode in here
except Exception as e:
logging.error(e, exc_info=True)
exc_info=
Kwarg'ın ne dediğini asla hatırlayamıyorum ; Teşekkürler!
logging.exception
İşim kısa bir süre önce uygulamamızdaki tüm geri bildirimleri / istisnaları günlüğe kaydetmemi sağladı. Başkalarının çevrimiçi olarak yayınladığı yukarıdaki gibi çok sayıda teknik denedim, ancak farklı bir yaklaşıma karar verdim. Geçersiz kılıyor traceback.print_exception
.
Http://www.bbarrows.com/ adresinde bir yazı var Bu okumak çok daha kolay olurdu ama ben de buraya yapıştırın.
Yazılımımızın vahşi ortamda karşılaşabileceği tüm istisnaları günlüğe kaydetmeyle görevlendirildiğinde, python istisna geri bildirimlerimizi günlüğe kaydetmek için bir dizi farklı teknik denedim. İlk başta python sistemi istisna kancası, sys.excepthook günlük kodunu eklemek için mükemmel bir yer olacağını düşündüm. Şuna benzer bir şey deniyordum:
import traceback
import StringIO
import logging
import os, sys
def my_excepthook(excType, excValue, traceback, logger=logger):
logger.error("Logging an uncaught exception",
exc_info=(excType, excValue, traceback))
sys.excepthook = my_excepthook
Bu ana iş parçacığı için çalıştı ama yakında benim sys.excepthook benim işlem başladı herhangi bir yeni iş parçacıkları arasında var olmadığını bulundu. Bu çok büyük bir konudur çünkü her şey bu projedeki iş parçacıklarında olur.
Googling ve bol miktarda belge okuduktan sonra bulduğum en yararlı bilgiler Python Issue tracker'dan geldi.
İplikteki ilk direk, sys.excepthook
dişler arasında devam etmeyen NOT'un çalışan bir örneğini gösterir (aşağıda gösterildiği gibi). Görünüşe göre bu beklenen davranıştır.
import sys, threading
def log_exception(*args):
print 'got exception %s' % (args,)
sys.excepthook = log_exception
def foo():
a = 1 / 0
threading.Thread(target=foo).start()
Bu Python Issue dizisindeki mesajlar gerçekten önerilen 2 hack ile sonuçlanır. Thread
İstisnaları yakalamak ve günlüğe kaydetmek için run yöntemini alt sınıftan ayırın ve kendi denememizde sarın veya threading.Thread.run
blok ve istisnalar hariç kendi denemenizde çalıştırmak için maymun yaması .
Alt sınıflamanın ilk yöntemi, her gün Thread
özel bir Thread
sınıfınızı bir günlük iş parçacığına sahip olmak istediğinizde içe aktarmak ve kullanmak zorunda kalacağınız için kodunuzda daha az zarif görünüyor . Tüm kod tabanımızı aramak ve tüm normalleri Threads
bu özel ile değiştirmek zorunda kaldım çünkü bu bir güçlük oldu Thread
. Bununla birlikte, bunun ne yaptığı açıktı Thread
ve özel günlük kodunda bir sorun olduğunda birisinin teşhis ve hata ayıklaması daha kolay olurdu. Özel günlük kaydı iş parçacığı şöyle görünebilir:
class TracebackLoggingThread(threading.Thread):
def run(self):
try:
super(TracebackLoggingThread, self).run()
except (KeyboardInterrupt, SystemExit):
raise
except Exception, e:
logger = logging.getLogger('')
logger.exception("Logging an uncaught exception")
Maymun yamasının ikinci yöntemi threading.Thread.run
güzel çünkü hemen sonra bir kez çalıştırabilirim __main__
ve günlük kodumu tüm istisnalarda kullanabilirim. Maymun yama, bir şeyin beklenen işlevselliğini değiştirdiği için hata ayıklamak için can sıkıcı olabilir. Python Issue tracker'dan önerilen yama:
def installThreadExcepthook():
"""
Workaround for sys.excepthook thread bug
From
http://spyced.blogspot.com/2007/06/workaround-for-sysexcepthook-bug.html
(https://sourceforge.net/tracker/?func=detail&atid=105470&aid=1230540&group_id=5470).
Call once from __main__ before creating any threads.
If using psyco, call psyco.cannotcompile(threading.Thread.run)
since this replaces a new-style class method.
"""
init_old = threading.Thread.__init__
def init(self, *args, **kwargs):
init_old(self, *args, **kwargs)
run_old = self.run
def run_with_except_hook(*args, **kw):
try:
run_old(*args, **kw)
except (KeyboardInterrupt, SystemExit):
raise
except:
sys.excepthook(*sys.exc_info())
self.run = run_with_except_hook
threading.Thread.__init__ = init
İstisna günlüğümü test etmeye başlayana kadar her şey yanlış gittiğimi fark ettim.
Test etmek için bir
raise Exception("Test")
kodumda bir yerde. Ancak, bu yöntemi çağırmak aa yöntemini sarma, geri izleme yazdırdı ve özel durumu yuttu blok dışında bir deneyin oldu. Bu çok sinir bozucuydu çünkü izlemenin STDOUT'a basıldığını gördüm ama günlüğe kaydedilmedim. Daha sonra, izlemeleri günlüğe kaydetmenin çok daha kolay bir yönteminin, sadece pcehon kodunun traceback.print_exception adlı izleri yazdırmak için kullandığı yöntemi düzeltmek olduğuna karar verdim. Aşağıdakine benzer bir şey buldum:
def add_custom_print_exception():
old_print_exception = traceback.print_exception
def custom_print_exception(etype, value, tb, limit=None, file=None):
tb_output = StringIO.StringIO()
traceback.print_tb(tb, limit, tb_output)
logger = logging.getLogger('customLogger')
logger.error(tb_output.getvalue())
tb_output.close()
old_print_exception(etype, value, tb, limit=None, file=None)
traceback.print_exception = custom_print_exception
Bu kod, izleme dizesini bir String Buffer'a yazar ve bunu ERROR günlüğüne kaydeder. ERROR seviye günlükleri alır ve analiz için eve gönderir 'customLogger' logger kurmak özel bir günlük işleyicisi var.
add_custom_print_exception
bağlandığınız sitede görünmüyor ve bunun yerine orada oldukça farklı bir son kod var. Hangisinin daha iyi / daha nihai olduğunu söylerdiniz ve neden? Teşekkürler!
logger.error(traceback.format_tb())
, istisna bilgisi de istiyorsanız (veya format_exc () öğesini çağırabilirsiniz .
sys.excepthook
Belki de exc_info
Python'un günlüğe kaydetme işlevlerinin parametresini kullanarak bir işleyici atayarak ana iş parçacığında yakalanmamış tüm özel durumları günlüğe kaydedebilirsiniz :
import sys
import logging
logging.basicConfig(filename='/tmp/foobar.log')
def exception_hook(exc_type, exc_value, exc_traceback):
logging.error(
"Uncaught exception",
exc_info=(exc_type, exc_value, exc_traceback)
)
sys.excepthook = exception_hook
raise Exception('Boom')
Programınız kullandığı ipler, ancak, daha sonra kullanılarak oluşturulan bu konuları dikkate ederse threading.Thread
olacak değil tetiği sys.excepthook
de belirtildiği gibi yakalanmamış istisna, içlerinde meydana geldiğinde Issue 1230540 Python'un sorun izleyicide üzerinde. Orjinalini bir blokta saran ve çağrı yapan alternatif bir yöntemle maymun yaması gibi bazı kısıtlamaların bu sınırlamanın üstesinden Thread.__init__
gelmesi önerildi.self.run
run
try
sys.excepthook
içindeki except
blok. Alternatif olarak, her bir iş parçacığınızın giriş noktasını kendiniz try
/ except
kendiniz manuel olarak sarabilirsiniz .
Yakalanmayan istisna iletileri STDERR'a gider, bu nedenle Python'da kendi günlüklemenizi uygulamak yerine Python komut dosyanızı çalıştırmak için kullandığınız kabuğu kullanarak bir dosyaya STDERR gönderebilirsiniz. Bash betiğinde, bunu BASH kılavuzunda açıklandığı gibi çıkış yeniden yönlendirmesi ile yapabilirsiniz. .
Dosyaya, diğer çıkışları terminale ekleyin:
./test.py 2>> mylog.log
Araya eklenen STDOUT ve STDERR çıktısıyla dosyanın üzerine yaz:
./test.py &> mylog.log
Ne aradım:
import sys
import traceback
exc_type, exc_value, exc_traceback = sys.exc_info()
traceback_in_var = traceback.format_tb(exc_traceback)
Görmek:
Geri izleme herhangi bir düzeyde (DEBUG, INFO, ...) bir logger kullanarak alabilirsiniz. Kullanırken logging.exception
, seviyenin HATA olduğunu unutmayın.
# test_app.py
import sys
import logging
logging.basicConfig(level="DEBUG")
def do_something():
raise ValueError(":(")
try:
do_something()
except Exception:
logging.debug("Something went wrong", exc_info=sys.exc_info())
DEBUG:root:Something went wrong
Traceback (most recent call last):
File "test_app.py", line 10, in <module>
do_something()
File "test_app.py", line 7, in do_something
raise ValueError(":(")
ValueError: :(
DÜZENLE:
Bu da işe yarar (python 3.6 kullanarak)
logging.debug("Something went wrong", exc_info=True)
İşte sys.excepthook kullanan bir sürüm
import traceback
import sys
logger = logging.getLogger()
def handle_excepthook(type, message, stack):
logger.error(f'An unhandled exception occured: {message}. Traceback: {traceback.format_tb(stack)}')
sys.excepthook = handle_excepthook
{traceback.format_exc()}
Bunun yerine kullanmaya ne dersiniz {traceback.format_tb(stack)}
?
belki o kadar şık değil, ama daha kolay:
#!/bin/bash
log="/var/log/yourlog"
/path/to/your/script.py 2>&1 | (while read; do echo "$REPLY" >> $log; done)
Heres python 2.6 belgelerinden alınan basit bir örnek :
import logging
LOG_FILENAME = '/tmp/logging_example.out'
logging.basicConfig(filename=LOG_FILENAME,level=logging.DEBUG,)
logging.debug('This message should go to the log file')