Adalah mungkin untuk mengubah tingkat log menggunakan fileConfig di python tanpa me-restart aplikasi. Jika hal ini tidak dapat dicapai melalui fileConfig ada beberapa cara lain untuk mendapatkan hasil yang sama?
Update: Ini adalah sebuah aplikasi yang berjalan pada server, saya ingin sys admin untuk dapat mengubah file konfigurasi yang akan diambil selama jangka waktu dengan aplikasi dan mengubah tingkat log secara dinamis. Saya bekerja dengan gevent pada saat itu maka saya've menambahkan kode saya sebagai salah satu jawaban yang menggunakan inotify untuk memilih perubahan pada file konfigurasi.
fileConfig
adalah sebuah mekanisme untuk mengkonfigurasi tingkat log untuk anda berdasarkan file; anda dapat secara dinamis mengubah hal ini setiap waktu dalam program anda.
Call .setLevel()
pada pendataan objek yang anda ingin mengubah tingkat log. Biasanya anda'a apa yang di root:
logging.getLogger().setLevel(logging.DEBUG)
Selain diterima jawaban: Tergantung pada bagaimana anda diinisialisasi logger, anda mungkin juga harus memperbarui logger's handler:
import logging
level = logging.DEBUG
logger = logging.getLogger()
logger.setLevel(level)
for handler in logger.handlers:
handler.setLevel(level)
Hal ini tentu saja mungkin untuk menggunakan fileConfig()
untuk mengubah konfigurasi penebangan on the fly, meskipun untuk perubahan sederhana pendekatan program seperti yang disarankan di Martijn Pieters' jawaban yang mungkin akan sesuai. Penebangan bahkan menyediakan socket server untuk mendengarkan perubahan konfigurasi menggunakan listen()
/ stopListening()
Api, seperti yang didokumentasikan di sini. Untuk mendapatkan login untuk mendengarkan pada port tertentu, anda menggunakan
t = logging.config.listen(PORT_NUMBER)
t.start()
dan untuk berhenti mendengarkan panggilan
logging.config.stopListening()
Untuk mengirim data ke server, anda dapat menggunakan misalnya
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('localhost', PORT_NUMBER))
with open(CONFIG_FILE) as f:
data_to_send = f.read()
s.send(struct.pack('>L', len(data_to_send)))
s.send(data_to_send)
s.close()
Update: Karena untuk mundur kompatibilitas kendala, internal pelaksanaan fileConfig()
call berarti bahwa anda dapat't menentukan disable_existing_loggers=False
dalam panggilan, yang membuat fitur ini kurang berguna dalam skenario tertentu. Anda dapat menggunakan API untuk mengirim file JSON menggunakan dictConfig skema, yang akan memungkinkan kontrol yang lebih baik atas rekonfigurasi. Hal ini membutuhkan Python 2.7/3.2 atau di atas (di mana dictConfig()
ditambahkan). Atau, anda dapat menggunakan stdlib kode untuk menerapkan sendiri pendengar yang bekerja dalam cara yang sama tetapi yang disesuaikan untuk kebutuhan spesifik anda.
Memperluas pada sfinken's jawaban, dan Starman's berikutnya komentar, anda juga dapat memeriksa jenis handler untuk target tertentu outputter - misalnya:
impor logging logger = logging.getLogger() untuk handler di logger.penangan: jika isinstance(handler, jenis(logging.StreamHandler())): handler.setLevel(logging.DEBUG) logger.debug('Debug logging diaktifkan')
Mungkin ini yang anda cari:
import logging
logging.getLogger().setLevel(logging.INFO)
Perhatikan bahwa `getLogger () dipanggil tanpa argumen mengembalikan akar logger.
Saya akhirnya menetap dengan menggunakan inotify dan gevent untuk memeriksa file menulis operasi, dan setelah saya tahu file yang telah diubah, maka aku pergi dan mengatur tingkat untuk setiap logger saya telah didasarkan pada config.
import gevent
import gevent_inotifyx as inotify
from gevent.queue import Queue
class FileChangeEventProducer(gevent.Greenlet):
def __init__(self, fd, queue):
gevent.Greenlet.__init__(self)
self.fd = fd
self.queue = queue
def _run(self):
while True:
events = inotify.get_events(self.fd)
for event in events:
self.queue.put(event)
gevent.sleep(0)
class FileChangeEventConsumer(gevent.Greenlet):
def __init__(self, queue, callBack):
gevent.Greenlet.__init__(self)
self.queue = queue
self.callback = callBack
def _run(self):
while True:
_ = self.queue.get()
self.callback()
gevent.sleep(0)
class GeventManagedFileChangeNotifier:
def __init__(self, fileLocation, callBack):
self.fileLocation = fileLocation
self.callBack = callBack
self.queue = Queue()
self.fd = inotify.init()
self.wd = inotify.add_watch(self.fd, self.fileLocation, inotify.IN_CLOSE_WRITE)
def start(self):
producer = FileChangeEventProducer(self.fd, self.queue)
producer.start()
consumer = FileChangeEventConsumer(self.queue, self.callBack)
consumer.start()
return (producer, consumer)
Kode di atas akan digunakan seperti di bawah ini,
def _setUpLoggingConfigFileChangeNotifier(self):
loggingFileNameWithFullPath = self._getFullPathForLoggingConfig()
self.gFsNotifier = GeventManagedFileChangeNotifier(loggingFileNameWithFullPath, self._onLogConfigChanged)
self.fsEventProducer, self.fsEventConsumer = self.gFsNotifier.start()
def _onLogConfigChanged(self):
self.rootLogger.info('Log file config has changed - examining the changes')
newLoggingConfig = Config(self.resourcesDirectory, [self.loggingConfigFileName]).config.get('LOG')
self.logHandler.onLoggingConfigChanged(newLoggingConfig)
Setelah saya baru log file config yang saya dapat kawat di kanan penebangan tingkat untuk setiap logger dari config. Saya hanya ingin berbagi jawaban dan itu mungkin membantu seseorang jika mereka mencoba untuk menggunakannya dengan gevent.
Tergantung pada aplikasi anda, anda harus terlebih dahulu menemukan cara untuk reload file atau mengatur ulang tingkat log didasarkan pada file konfigurasi anda sendiri selama eksekusi.
Cara termudah adalah dengan menggunakan timer. Baik menggunakan threading untuk melakukan itu, atau membuat anda async kerangka kerja untuk melakukan itu (jika anda menggunakan salah; mereka biasanya melakukan hal ini).
Menggunakan threading.Timer:
import threading
import time
def reset_level():
# you can reload your own config file or use logging.config.fileConfig here
print 'Something else'
pass
t = threading.Timer(10, reset_level)
t.start()
while True:
# your app code
print 'Test'
time.sleep(2)
Output:
Test
Test
Test
Test
Test
Something else
Test
Test
Update: Silahkan periksa solusi yang diusulkan oleh Martijn Pieters.