Saya menggunakan logger python. Berikut ini adalah kode saya:
import os
import time
import datetime
import logging
class Logger :
def myLogger(self):
logger = logging.getLogger('ProvisioningPython')
logger.setLevel(logging.DEBUG)
now = datetime.datetime.now()
handler=logging.FileHandler('/root/credentials/Logs/ProvisioningPython'+ now.strftime("%Y-%m-%d") +'.log')
formatter = logging.Formatter('%(asctime)s %(levelname)s %(message)s')
handler.setFormatter(formatter)
logger.addHandler(handler)
return logger
Masalah yang saya miliki adalah saya mendapatkan banyak entri di file log untuk setiap logger.info
panggilan. Bagaimana saya bisa memecahkan masalah ini?
Jawaban:
Ini
logging.getLogger()
sudah menjadi tunggal. ( Dokumentasi )Masalahnya adalah setiap kali Anda memanggil
myLogger()
, itu menambahkan penangan lain ke instance, yang menyebabkan log duplikat.Mungkin sesuatu seperti ini?
sumber
loggers.update(dict(name=logger))
? tidakloggers[name] = logger
lebih sederhana?loggers.update(dict(name=logger))
akan membuat kamus dengan satu kunci yang dipanggilname
dan terus memperbarui kunci yang sama. Saya terkejut tidak ada yang tidak menyebutkan ini sebelumnya karena kode ini cukup rusak :) Akan membuat perubahan yang diperlukan.loggers
kamus global itu berlebihanlogging.getLogger
? karena Anda benar-benar hanya ingin menghindari penambahan penangan ekstra, sepertinya Anda lebih suka jawaban di bawah ini yang memeriksa penangan secara langsungSejak Python 3.2 Anda bisa memeriksa apakah penangan sudah ada dan jika demikian, kosongkan mereka sebelum menambahkan penangan baru. Ini cukup nyaman saat debugging dan kode menyertakan inisialisasi logger Anda
sumber
membuat trik untuk saya
menggunakan python 2.7
sumber
Saya sudah menggunakan
logger
sebagai Singleton dan diperiksaif not len(logger.handlers)
, tetapi masih mendapat duplikat : Itu adalah keluaran yang diformat, diikuti dengan yang tidak diformat.Solusi dalam kasus saya:
logger.propagate = False
Penghargaan untuk jawaban ini dan dokumen .
sumber
Anda menelepon
Logger.myLogger()
lebih dari sekali. Menyimpan contoh logger itu kembali di suatu tempat dan menggunakan kembali itu .Harap diperhatikan juga bahwa jika Anda masuk sebelum penangan ditambahkan, default
StreamHandler(sys.stderr)
akan dibuat.sumber
Ini adalah tambahan untuk jawaban @ rm957377 tetapi dengan penjelasan mengapa hal ini terjadi . Saat Anda menjalankan fungsi lambda di AWS, mereka memanggil fungsi Anda dari dalam contoh pembungkus yang tetap hidup untuk beberapa panggilan. Artinya, jika Anda memanggil
addHandler()
dalam kode fungsi Anda, itu akan terus menambahkan penangan duplikat ke singleton logging setiap kali fungsi berjalan. Singleton logging tetap ada melalui beberapa panggilan fungsi lambda Anda.Untuk mengatasi ini, Anda dapat menghapus penangan Anda sebelum Anda mengaturnya melalui:
sumber
.info()
panggilan yang saya tidak mengerti.Logger Anda harus bekerja sebagai tunggal. Anda tidak boleh membuatnya lebih dari sekali. Berikut adalah contoh tampilannya:
sumber
Implementasi logger sudah tunggal.
Sumber- Menggunakan logging di beberapa modul
Jadi cara Anda memanfaatkan ini adalah -
Misalkan kita telah membuat dan mengkonfigurasi logger yang disebut 'main_logger' di modul utama (yang hanya mengkonfigurasi logger, tidak mengembalikan apa pun).
Sekarang di sub-modul, jika kita membuat logger anak mengikuti hierarki penamaan 'main_logger.sub_module_logger' , kita tidak perlu mengkonfigurasinya di sub-modul. Cukup pembuatan logger yang mengikuti hierarki penamaan sudah cukup.
Dan itu tidak akan menambahkan penangan duplikat juga.
Lihat pertanyaan ini untuk jawaban yang lebih bertele-tele.
sumber
logger = logging.getLogger('my_logger') ; logger.handlers = [logger.handlers[0], ]
Double (atau triple atau ..- berdasarkan jumlah reload) output logger juga dapat terjadi saat Anda memuat ulang modul Anda melalui
importlib.reload
(untuk alasan yang sama seperti yang dijelaskan dalam jawaban yang diterima). Saya menambahkan jawaban ini hanya untuk referensi di masa mendatang karena saya butuh beberapa saat untuk mencari tahu mengapa keluaran saya adalah dupli (tiga kali lipat).sumber
Salah satu solusi sederhana adalah seperti
Dengan cara ini Anda menghindari penambahan penangan baru ke daftar "penangan" yang mendasarinya.
sumber
Intinya untuk sebagian besar kasus ketika ini terjadi, seseorang hanya perlu memanggil logger.getLogger () hanya sekali per modul. Jika Anda memiliki beberapa kelas seperti yang saya lakukan, saya dapat menyebutnya seperti ini:
Keduanya kemudian akan memiliki nama paket lengkap dan metode tempat login.
sumber
Anda bisa mendapatkan daftar semua penangan untuk logger tertentu, jadi Anda bisa melakukan sesuatu seperti ini
Dalam contoh di atas kami memeriksa apakah penangan untuk file yang ditentukan sudah terhubung ke pencatat, tetapi memiliki akses ke daftar semua penangan memberi Anda kemampuan untuk memutuskan kriteria mana Anda harus menambahkan penangan lain atau tidak.
sumber
Punya masalah ini hari ini. Karena fungsi saya adalah @staticmethod, saran di atas diselesaikan dengan random ().
Tampak seperti:
sumber
sumber