Saya memiliki proyek python kecil yang memiliki struktur berikut -
Project
-- pkg01
-- test01.py
-- pkg02
-- test02.py
-- logging.conf
Saya berencana untuk menggunakan modul logging standar untuk mencetak pesan ke stdout dan file log. Untuk menggunakan modul logging, diperlukan beberapa inisialisasi -
import logging.config
logging.config.fileConfig('logging.conf')
logger = logging.getLogger('pyApp')
logger.info('testing')
Saat ini, saya melakukan inisialisasi ini di setiap modul sebelum saya mulai mencatat pesan. Apakah mungkin untuk melakukan inisialisasi ini hanya sekali di satu tempat sehingga pengaturan yang sama digunakan kembali dengan masuk ke seluruh proyek?
fileConfig
setiap modul yang melakukan logging, kecuali Anda memilikiif __name__ == '__main__'
logika di dalamnya. Jawaban prost bukanlah praktik yang baik jika paket tersebut adalah pustaka, meskipun mungkin cocok untuk Anda - seseorang tidak boleh mengonfigurasi login dalam paket pustaka, selain menambahkan aNullHandler
.package/__init__.py
. Itu biasanya bukan tempat Anda meletakkanif __name__ == '__main__'
kode. Juga, contoh prost kelihatannya akan memanggil kode konfigurasi tanpa syarat pada impor, yang tidak cocok untuk saya. Secara umum, kode konfigurasi logging harus dilakukan di satu tempat dan tidak boleh terjadi sebagai efek samping dari impor kecuali ketika Anda mengimpor __main__.if __name__ == '__main__'
? (tidak disebutkan secara eksplisit dalam pertanyaan jika ini masalahnya)Jawaban:
Praktik terbaik adalah, di setiap modul, untuk memiliki logger yang didefinisikan seperti ini:
di dekat bagian atas modul, dan kemudian di kode lain dalam modul lakukan misalnya
Jika Anda perlu membagi aktivitas logging di dalam sebuah modul, gunakan mis
dan masuk
loggerA
danloggerB
jika perlu.Di program atau program utama Anda, lakukan misalnya:
atau
Lihat di sini untuk login dari beberapa modul, dan di sini untuk konfigurasi logging untuk kode yang akan digunakan sebagai modul perpustakaan dengan kode lain.
Pembaruan: Saat menelepon
fileConfig()
, Anda mungkin ingin menentukandisable_existing_loggers=False
apakah Anda menggunakan Python 2.6 atau yang lebih baru (lihat dokumen untuk informasi lebih lanjut). Nilai default adalahTrue
untuk kompatibilitas mundur, yang menyebabkan semua penebang yang ada dinonaktifkan olehfileConfig()
kecuali mereka atau leluhur mereka secara eksplisit disebutkan dalam konfigurasi. Dengan nilai yang disetelFalse
, penebang yang ada dibiarkan sendiri. Jika menggunakan Python 2.7 / Python 3.2 atau yang lebih baru, Anda mungkin ingin mempertimbangkandictConfig()
API yang lebih baik daripadafileConfig()
karena memberikan kontrol lebih besar atas konfigurasi.sumber
disable_existing_loggers
bendera yang secaraTrue
default tetapi dapat diatur keFalse
.Sebenarnya setiap logger adalah anak dari paket logger orangtua (yaitu
package.subpackage.module
mewarisi konfigurasi daripackage.subpackage)
, jadi yang perlu Anda lakukan hanyalah mengkonfigurasi logger root. Ini dapat dicapai denganlogging.config.fileConfig
(konfigurasi Anda sendiri untuk logger) ataulogging.basicConfig
(set logger root) Setup logging di modul entri Anda (__main__.py
atau apa pun yang ingin Anda jalankan, misalnyamain_script.py
.__init__.py
Berfungsi juga)menggunakan basicConfig:
menggunakan fileConfig:
lalu buat setiap logger menggunakan:
Untuk informasi lebih lanjut, lihat Tutorial Logging Lanjutan .
sumber
__main__.py
(mis. Jika saya ingin menggunakan modul dalam skrip yang tidak memiliki logger)logging.getLogger(__name__)
masih akan melakukan semacam logging di modul atau akankah itu menimbulkan pengecualian?Saya selalu melakukannya seperti di bawah ini.
Gunakan file python tunggal untuk mengkonfigurasi log saya sebagai pola tunggal yang bernama '
log_conf.py
'Di modul lain, cukup impor konfigurasi.
Ini adalah pola tunggal untuk dicatat, sederhana dan efisien.
sumber
Beberapa jawaban ini menunjukkan bahwa di bagian atas modul Anda melakukannya
Ini adalah pemahaman saya bahwa ini dianggap praktik yang sangat buruk . Alasannya adalah bahwa konfigurasi file akan menonaktifkan semua logger yang ada secara default. Misalnya
Dan di modul utama Anda:
Sekarang log yang ditentukan dalam logging.ini akan kosong, karena logger yang ada dinonaktifkan oleh panggilan fileconfig.
Meskipun dimungkinkan untuk mengatasi hal ini (disable_existing_Loggers = False), secara realistis banyak klien perpustakaan Anda tidak akan tahu tentang perilaku ini, dan tidak akan menerima log Anda. Permudah klien Anda dengan selalu menelepon logging.getLogger secara lokal. Tip Hat: Saya belajar tentang perilaku ini dari Situs Victor Lin .
Jadi praktik yang baik adalah sebaliknya untuk selalu memanggil logging.getLogger secara lokal. Misalnya
Juga, jika Anda menggunakan fileconfig di utama Anda, setel disable_existing_loggers = Salah, kalau-kalau perancang perpustakaan Anda menggunakan instance logger level modul.
sumber
logging.config.fileConfig('logging.ini')
sebelumnyaimport my_module
? Seperti yang disarankan dalam jawaban ini .logger = logging.getLogger(__name__)
'Cara sederhana menggunakan salah satu contoh pendataan pustaka di banyak modul bagi saya adalah solusi berikut:
base_logger.py
File lainnya
sumber
Melemparkan solusi lain.
Dalam init modul saya .py Saya punya sesuatu seperti:
Kemudian di setiap modul saya perlu logger, saya lakukan:
Ketika log terjawab, Anda dapat membedakan sumbernya dengan modul asalnya.
sumber
Anda juga bisa membuat sesuatu seperti ini!
Sekarang Anda dapat menggunakan beberapa penebang dalam modul yang sama dan di seluruh proyek jika yang di atas didefinisikan dalam modul yang terpisah dan diimpor dalam modul-modul lain diperlukan pencatatan.
sumber
@ Solusi Yarkee tampak lebih baik. Saya ingin menambahkan sesuatu ke sana -
Jadi LoggerManager dapat menjadi pluggable ke seluruh aplikasi. Semoga ini masuk akal dan berharga.
sumber
Ada beberapa jawaban. Saya berakhir dengan solusi serupa namun berbeda yang masuk akal bagi saya, mungkin itu akan masuk akal bagi Anda juga. Tujuan utama saya adalah untuk dapat mengirimkan log ke penangan berdasarkan levelnya (debug level log ke konsol, peringatan dan di atas ke file):
membuat file util yang bagus bernama logger.py:
flask.app adalah nilai hardcode dalam flask. logger aplikasi selalu dimulai dengan flask.app sebagai nama modulnya.
sekarang, di setiap modul, saya dapat menggunakannya dalam mode berikut:
Ini akan membuat log baru untuk "app.flask.MODULE_NAME" dengan upaya minimal.
sumber
Praktik terbaik adalah membuat modul secara terpisah yang hanya memiliki satu metode yang tugasnya kita berikan penangan logger ke metode pemanggilan. Simpan file ini sebagai m_logger.py
Sekarang panggil metode getlogger () setiap kali logger handler diperlukan.
sumber
--debug
opsi di aplikasi dan ingin mengatur tingkat logging di semua penebang di aplikasi Anda berdasarkan parameter ini ...get_logger(level=logging.INFO)
untuk mengembalikan beberapa jenis singleton, jadi ketika dipanggil pertama kali dari aplikasi utama, ia menginisialisasi logger dan handler dengan level yang tepat dan kemudian mengembalikanlogger
objek yang sama ke semua metode lain.Baru menggunakan python, jadi saya tidak tahu apakah ini disarankan, tetapi berfungsi dengan baik untuk tidak menulis ulang boilerplate.
Proyek Anda harus memiliki init .py sehingga dapat dimuat sebagai modul
sys._getframe(1)
saran datang dari siniKemudian untuk menggunakan logger Anda di file lain:
Peringatan:
import [your module]
tidak , tidak akan berfungsi:python -m [your module name].[your filename without .py]
__main__
, tetapi solusi apa pun yang menggunakan__name__
akan memiliki masalah itu.sumber