2012-02-16 30 views
8

Tôi đã cố gắng tạo thuộc tính tùy chỉnh để ghi nhật ký (tên lớp của người gọi, tên mô-đun, v.v.) và bị kẹt với một ngoại lệ lạ cho tôi biết rằng cá thể LogRecord được tạo trong tiến trình không có các thuộc tính cần thiết. Sau một chút thử nghiệm tôi đã kết thúc với điều này:Mô-đun đăng nhập Python: logger tùy chỉnh

import logging 

class MyLogger(logging.getLoggerClass()): 
    value = None 

logging.setLoggerClass(MyLogger) 

loggers = [ 
    logging.getLogger(), 
    logging.getLogger(""), 
    logging.getLogger("Name") 
] 

for logger in loggers: 
    print(isinstance(logger, MyLogger), hasattr(logger, "value")) 

này mảnh dường như đúng đắn về sản lượng mã:

False False 
False False 
True True 

Lỗi hoặc tính năng?

Trả lời

5

Nhìn vào mã nguồn chúng ta có thể thấy như sau:

root = RootLogger(WARNING) 
def getLogger(name=None): 
    if name: 
     return Logger.manager.getLogger(name) 
    else: 
     return root 

Đó là, một logger gốc được tạo ra theo mặc định khi các mô-đun được nhập khẩu. Do đó, mỗi lần bạn tìm kiếm thư mục gốc (chuyển một giá trị sai như chuỗi rỗng), bạn sẽ nhận được đối tượng logging.RootLogger bất kể có bất kỳ lệnh gọi nào đến logging.setLoggerClass.

Về lớp logger được sử dụng chúng ta có thể thấy:

_loggerClass = None 
def setLoggerClass(klass): 
    ... 
    _loggerClass = klass 

Điều này có nghĩa rằng một biến toàn cầu tổ chức lớp logger sẽ được sử dụng trong tương lai.

Thêm vào đó, nhìn vào logging.Manager (được sử dụng bởi logging.getLogger), chúng ta có thể thấy điều này:

def getLogger(self, name): 
    ... 
      rv = (self.loggerClass or _loggerClass)(name) 

Nghĩa là, nếu self.loggerClass không được thiết lập (trong đó sẽ không được trừ khi bạn đã rõ ràng đặt nó), lớp từ biến toàn cầu được sử dụng.

Do đó, đó là một tính năng. Trình ghi nhật ký gốc luôn là đối tượng logging.RootLogger và các đối tượng nhật ký khác được tạo dựa trên cấu hình tại thời điểm đó.

2

logging.getLogger()logging.getLogger("") không gửi lại một MyLogger vì họ trả lại logger thư mục gốc của hệ thống phân cấp khai thác gỗ, như mô tả trong logging documentation:

logging.getLogger ([name])

Return một logger với tên được chỉ định hoặc, nếu không có tên nào được chỉ định, trả về một logger, đó là logger gốc của hệ thống phân cấp.

Như vậy, là bạn có logger thiết lập:

>>> logging.getLogger() 
<logging.RootLogger object at 0x7d9450> 
>>> logging.getLogger("foo") 
<test3.MyLogger object at 0x76d9f0> 

Tôi không nghĩ rằng đây có liên quan đến KeyError bạn bắt đầu bài đăng. Bạn nên đăng mã khiến cho ngoại lệ đó bị ném (test.py).

+0

Cảm ơn bạn đã bình luận, tôi đã chỉnh sửa câu hỏi. Nhưng tôi nghĩ rằng hành vi này không phải là điều mà người ta mong đợi sẽ xảy ra. – Pastafarianist

+0

Tại sao nó không phải là những gì bạn mong đợi sẽ xảy ra? Đó là * chính xác * những gì tài liệu nói sẽ xảy ra khi không có tên được chỉ định. –

+4

Mặc dù đây là những gì tài liệu nói, nó phản trực giác. Thiết lập một lớp cho logger, tôi mong đợi các logger _all_ có lớp đó, bao gồm cả lớp gốc và loại bỏ các lớp đã khởi tạo. – Pastafarianist

Các vấn đề liên quan