Cara mencatat nama file sumber dan nomor baris dengan Python

123

Apakah mungkin untuk mendekorasi / memperluas sistem logging standar python, sehingga ketika metode logging dipanggil, ia juga mencatat file dan nomor baris di mana ia dipanggil atau mungkin metode yang memanggilnya?

digy
sumber

Jawaban:

228

Tentu, periksa pemformat di dokumen logging. Khususnya variabel lineno dan pathname.

% (pathname) s Nama path lengkap dari file sumber tempat panggilan logging dikeluarkan (jika tersedia).

% (nama file) s Bagian nama file dari nama jalur.

% (module) s Module (bagian nama dari nama file).

% (funcName) s Nama fungsi yang berisi panggilan logging.

% (lineno) d Nomor baris sumber tempat panggilan logging dikeluarkan (jika tersedia).

Tampak seperti ini:

formatter = logging.Formatter('[%(asctime)s] p%(process)s {%(pathname)s:%(lineno)d} %(levelname)s - %(message)s','%m-%d %H:%M:%S')
Seb
sumber
1
Dan, ya, kekacauan huruf besar / kecil dalam variabel perlu dipertimbangkan.
Tom Pohl
1
Atau disebut sebagai "kasus unta yang dilaksanakan dengan sangat buruk".
Jon Spencer
81

Di atas jawaban Seb yang sangat berguna , berikut adalah cuplikan kode praktis yang mendemonstrasikan penggunaan logger dengan format yang masuk akal:

#!/usr/bin/env python
import logging

logging.basicConfig(format='%(asctime)s,%(msecs)d %(levelname)-8s [%(filename)s:%(lineno)d] %(message)s',
    datefmt='%Y-%m-%d:%H:%M:%S',
    level=logging.DEBUG)

logger = logging.getLogger(__name__)
logger.debug("This is a debug log")
logger.info("This is an info log")
logger.critical("This is critical")
logger.error("An error occurred")

Menghasilkan keluaran ini:

2017-06-06:17:07:02,158 DEBUG    [log.py:11] This is a debug log
2017-06-06:17:07:02,158 INFO     [log.py:12] This is an info log
2017-06-06:17:07:02,158 CRITICAL [log.py:13] This is critical
2017-06-06:17:07:02,158 ERROR    [log.py:14] An error occurred
codeforester
sumber
5
Gunakan ini untuk detail lebih lanjut: formatter = logging.Formatter ('% (asctime) s,% (levelname) -8s [% (filename) s:% (module) s:% (funcName) s:% (lineno) d] % (message) s ')
Girish Gupta
apakah ada cara untuk mengubah hanya di satu tempat di bagian atas kode apakah pesan logging akan dicetak atau tidak? Saya ingin dua mode, satu dengan banyak cetakan untuk melihat apa yang sebenarnya dilakukan oleh program; dan satu, ketika sudah cukup stabil, di mana tidak ada keluaran yang ditampilkan.
Marie. P.
3
@ Marie.P. jangan ajukan pertanyaan berbeda dalam komentar. Jawabannya adalah tingkat logging.
bugmenot123
4

Untuk membangun di atas dengan cara mengirimkan logging debug ke standar:

import logging
import sys

root = logging.getLogger()
root.setLevel(logging.DEBUG)

ch = logging.StreamHandler(sys.stdout)
ch.setLevel(logging.DEBUG)
FORMAT = "[%(filename)s:%(lineno)s - %(funcName)20s() ] %(message)s"
formatter = logging.Formatter(FORMAT)
ch.setFormatter(formatter)
root.addHandler(ch)

logging.debug("I am sent to standard out.")

Menempatkan di atas ke dalam file bernama debug_logging_example.pymenghasilkan output:

[debug_logging_example.py:14 -             <module>() ] I am sent to standard out.

Kemudian jika Anda ingin mematikan komentar keluar root.setLevel(logging.DEBUG).

Untuk file tunggal (mis. Tugas kelas) saya telah menemukan cara yang jauh lebih baik untuk melakukan ini dibandingkan dengan menggunakan print()pernyataan. Jika memungkinkan Anda menonaktifkan keluaran debug di satu tempat sebelum Anda mengirimkannya.

jeruk nipis
sumber
1

Untuk dev yang menggunakan PyCharm atau Eclipse pydev, berikut ini akan menghasilkan tautan ke sumber pernyataan log di keluaran log konsol:

import logging, sys, os
logging.basicConfig(stream=sys.stdout, level=logging.DEBUG, format='%(message)s | \'%(name)s:%(lineno)s\'')
log = logging.getLogger(os.path.basename(__file__))


log.debug("hello logging linked to source")

Lihat hyperlink file sumber Pydev di konsol Eclipse untuk diskusi dan riwayat yang lebih lama.

karakter
sumber
0
# your imports above ...


logging.basicConfig(
    format='%(asctime)s,%(msecs)d %(levelname)-8s [%(pathname)s:%(lineno)d in 
    function %(funcName)s] %(message)s',
    datefmt='%Y-%m-%d:%H:%M:%S',
    level=logging.DEBUG
)

logger = logging.getLogger(__name__)

# your classes and methods below ...
# An naive Sample of usage:
try:
    logger.info('Sample of info log')
    # your code here
except Exception as e:
    logger.error(e)

Berbeda dari jawaban lain, ini akan mencatat jalur lengkap file dan nama fungsi yang mungkin telah terjadi kesalahan. Ini berguna jika Anda memiliki proyek dengan lebih dari satu modul dan beberapa file dengan nama yang sama didistribusikan di modul ini.

Hosana Gomes
sumber