Ghi nhật ký Python - Tắt ghi nhật ký từ các mô-đun đã nhập


100

Tôi đang sử dụng mô-đun ghi nhật ký Python và muốn tắt thông báo nhật ký được in bởi các mô-đun bên thứ ba mà tôi nhập. Ví dụ, tôi đang sử dụng một cái gì đó như sau:

logger = logging.getLogger()
logger.setLevel(level=logging.DEBUG)
fh = logging.StreamHandler()
fh_formatter = logging.Formatter('%(asctime)s %(levelname)s %(lineno)d:%(filename)s(%(process)d) - %(message)s')
fh.setFormatter(fh_formatter)
logger.addHandler(fh)

Điều này sẽ in ra các thông báo gỡ lỗi của tôi khi tôi thực hiện logger.debug ("tin nhắn của tôi!"), Nhưng nó cũng in ra các thông báo gỡ lỗi từ bất kỳ mô-đun nào tôi nhập (chẳng hạn như yêu cầu và một số thứ khác).

Tôi chỉ muốn xem thông báo nhật ký từ các mô-đun mà tôi quan tâm. Có thể làm cho mô-đun ghi nhật ký thực hiện việc này không?

Lý tưởng nhất, tôi muốn có thể yêu cầu trình ghi nhật ký in các thông báo từ "ModuleX, ModuleY" và bỏ qua tất cả những thứ khác.

Tôi đã xem phần sau, nhưng tôi không muốn phải tắt / bật ghi nhật ký trước mỗi lần gọi hàm đã nhập: ghi nhật ký - làm cách nào để bỏ qua nhật ký mô-đun đã nhập?

Câu trả lời:


70

Vấn đề là việc gọi getLoggermà không có đối số trả về trình ghi gốc, vì vậy khi bạn đặt cấp cho logging.DEBUGbạn cũng đang đặt cấp cho các mô-đun khác sử dụng trình ghi đó.

Bạn có thể giải quyết điều này bằng cách đơn giản là không sử dụng trình ghi gốc. Để thực hiện việc này, chỉ cần chuyển một tên làm đối số, ví dụ như tên mô-đun của bạn:

logger = logging.getLogger('my_module_name')
# as before

điều này sẽ tạo ra một trình ghi nhật ký mới và do đó nó sẽ không vô tình thay đổi cấp độ ghi nhật ký cho các mô-đun khác.


Rõ ràng là bạn phải sử dụng logger.debugthay vì vì logging.debugsau này là một hàm tiện lợi gọi debugphương thức của trình ghi gốc.

Điều này được đề cập trong Hướng dẫn ghi nhật ký nâng cao . Nó cũng cho phép bạn biết mô-đun nào đã kích hoạt thông báo nhật ký một cách đơn giản.


37
Tôi đang tạo một trình ghi nhật ký với __name__r nhưng tôi vẫn thấy các nhật ký từ các mô-đun đã nhập. Tôi đang cố gắng định cấu hình ghi nhật ký bằng tệp cấu hình ini. Tôi nên làm gì cho điều đó?
Durga Swaroop

8
Tạo một trình ghi nhật ký __name__cũng không hoạt động với tôi. Có lẽ vì tôi đang sử dụng một tập lệnh độc lập chứ không phải một "mô-đun"? Điều làm việc cho tôi là định cấu hình ghi nhật ký cho các mô-đun đã nhập ( matpplotlibtrong trường hợp của tôi) thông qua logging.getLogger("matplotlib").setLevel(logging.WARNING)và cho tập lệnh của tôi qua logging.basicConfig.
Bli

1
Tôi chỉ muốn làm nổi bật giá trị của dòng của bạn "Rõ ràng là bạn phải sử dụng logger.debugthay vì logging.debug". Đây là một sai lầm dễ dàng để làm cho sử dụng khai thác gỗ thay vì logger nhưng nó đã truất ngôi tất cả các cấu hình thông minh bạn muốn thiết lập. Tôi đã dành vài giờ cuối cùng để sống như thế này!
timdadev

@bli Có sự khác biệt lớn giữa việc ghi nhật ký khi phát triển thư viện so với khi phát triển tệp thực thi. Về cơ bản: nếu bạn đang viết một mô-đun / gói được nhập vào, bạn không nên cấu hình bất cứ thứ gì. Mô-đun chỉ nên chứa các logger = logging.getLogger('package.my_module')lệnh gọi và của bạn có thể logger.debug/warning, không có cấu hình các cấp ghi nhật ký hoặc trình xử lý. Khi bạn viết ứng dụng nhị phân ở đó, bạn nên quyết định mức độ cho các bản ghi và trình xử lý khác nhau. Các thư viện chứa cấu hình ghi nhật ký sẽ luôn là một vấn đề.
Bakuriu

Trong trường hợp của tôi, gói tôi nhập sử dụng trình ghi gốc (qua logging.info). Có cách nào để vô hiệu hóa cụ thể nhật ký gốc từ gói này không?
IanS

45

Nếu bạn định sử dụng logginggói python , quy ước chung để xác định trình ghi nhật ký trong mọi mô-đun sử dụng nó.

logger = logging.getLogger(__name__)

Nhiều gói python phổ biến thực hiện điều này, bao gồm requests. Nếu một gói sử dụng quy ước này, thật dễ dàng để bật / tắt ghi nhật ký cho nó, bởi vì tên bộ ghi sẽ trùng tên với gói (hoặc sẽ là con của bộ ghi đó). Bạn thậm chí có thể đăng nhập nó vào cùng một tệp với các trình ghi nhật ký khác của bạn.

logger = logging.getLogger(__name__)
logger.setLevel(logging.DEBUG)

requests_logger = logging.getLogger('requests')
requests_logger.setLevel(logging.DEBUG)

handler = logging.StreamHandler()
handler.setLevel(logging.DEBUG)
logger.addHandler(handler)
requests_logger.addHandler(handler)

15
Lưu ý rằng khi bạn cố gắng định cấu hình các trình ghi của mình như trong hướng dẫn cơ bản chính thức với logging.basicConfig(...)tất cả các trình ghi nhật ký giờ đây sẽ xuất ra logging.lastResort(bắt đầu với Python 3.2, là stderr) nếu không có trình xử lý nào được đưa ra hoặc trình xử lý bạn đã đặt. Vì vậy, không sử dụng nó hoặc bạn sẽ tiếp tục nhận được tất cả các thông báo nhật ký.
user136036

43

Không chắc liệu điều này có phù hợp để đăng hay không, nhưng tôi đã bị mắc kẹt trong một thời gian dài và muốn giúp đỡ bất kỳ ai có cùng vấn đề, vì tôi chưa tìm thấy nó ở bất kỳ nơi nào khác!

Tôi nhận được nhật ký gỡ lỗi từ matplotlib mặc dù đã làm theo tài liệu khá đơn giản tại hướng dẫn ghi nhật ký nâng caokhắc phục sự cố . Tôi đang khởi tạo trình đăng nhập của mình vào main()một tệp và nhập một hàm để tạo một âm mưu từ tệp khác (nơi tôi đã nhập matplotlib).

Điều phù hợp với tôi là thiết lập mức matplotlib trước khi nhập nó, thay vì sau như tôi đã làm cho các mô-đun khác trong tệp chính của mình. Điều này có vẻ trái ngược với tôi vì vậy nếu ai đó có hiểu biết sâu sắc về cách bạn có thể đặt cấu hình cho trình ghi nhật ký chưa được nhập, tôi sẽ rất tò mò muốn tìm hiểu cách hoạt động của điều này. Cảm ơn!

Trong tệp chính của tôi:

import logging
import requests
logger = logging.getLogger(__name__)
logger.setLevel(logging.DEBUG)
logging.getLogger('requests').setLevel(logging.DEBUG)

def main():
  ...

Trong plot.pytệp của tôi :

import logging
logging.getLogger('matplotlib').setLevel(logging.WARNING)
import matplotlib.pyplot as plt

def generatePlot():
  ...

Tôi gặp lỗi: Đối tượng 'Logger' không có thuộc tính 'DEBUG'. logger.DEBUGnên đượclogging.DEBUG
foxiris

Cảm ơn! Nó thực sự hữu ích! Tôi đặt mức ghi matplotlib sau cấu hình ghi nhật ký chính của mình và trước lệnh sẽ nhập matplotlib. Đã giải quyết!
gph

Tôi đã thiết lập đăng nhập cho matplotlibđến WARNING sau khi tôi đã nhập khẩu các mô-đun, kể từ khi thêm nó trước khi nhập sẽ cung cấp cho một lint-lỗi. Nó vẫn làm việc cho tôi. Tôi đang sử dụng matplotlib==3.3.2trong Python 3.7 nếu nó hữu ích.
End-2-End

9

@Bakuriu giải thích khá thanh lịch về chức năng. Ngược lại, bạn có thể sử dụng getLogger()phương pháp này để truy xuất và cấu hình lại / vô hiệu hóa các trình ghi không mong muốn.

Tôi cũng muốn thêm logging.fileConfig()phương thức chấp nhận một tham số được gọi disable_existing_loggerssẽ vô hiệu hóa bất kỳ trình ghi nhật ký nào đã xác định trước đó (tức là trong các mô-đun đã nhập).


9

Điều này vô hiệu hóa tất cả các trình ghi nhật ký hiện có, chẳng hạn như các trình ghi nhật ký được tạo bởi các mô-đun đã nhập, trong khi vẫn sử dụng trình ghi nhật ký gốc (và không cần phải tải tệp bên ngoài).

logging.config.dictConfig({
    'version': 1,
    'disable_existing_loggers': True,
})

Lưu ý rằng bạn cần nhập tất cả các mô-đun mà bạn không muốn đăng nhập trước! Nếu không, những người đó sẽ không được coi là "người ghi nhật ký hiện có". Sau đó, nó sẽ vô hiệu hóa tất cả các trình ghi từ các mô-đun đó. Điều này có thể dẫn đến việc bạn cũng bỏ lỡ các lỗi quan trọng!

Để biết thêm các ví dụ chi tiết sử dụng các tùy chọn liên quan cho cấu hình, hãy xem https://gist.github.com/st4lk/6287746đây là một ví dụ (hoạt động một phần) sử dụng YAML để cấu hình với coloredlogthư viện.


Câu hỏi của bạn là gì?
user1767754

1
requestVí dụ: điều này hoạt động , nhưng nó sẽ không hoạt động khi các mô-đun được nhập tạo nhật ký của chúng bên trong lớp mà bạn sẽ gọi sau, giống như APSchedulerkhi bạn gọi BackgroundScheduler.BackgroundScheduler(). Xem ở đây để có giải pháp: stackoverflow.com/a/48891485/2441026
user136036

Điều này phù hợp với trường hợp của tôi với tệp cấu hình yaml
user4015990

4

Bạn có thể sử dụng một cái gì đó như:

logging.getLogger("imported_module").setLevel(logging.WARNING)
logging.getLogger("my_own_logger_name").setLevel(logging.DEBUG)

Điều này sẽ đặt cấp độ nhật ký của mô-đun của riêng tôi thành GỠ LỖI, đồng thời ngăn mô-đun đã nhập sử dụng cùng cấp.

Lưu ý: "imported_module"có thể được thay thế bằng imported_module.__name__(không có dấu ngoặc kép) và "my_own_logger_name"có thể được thay thế bằng __name__nếu đó là cách bạn thích làm.


1

Tôi đã từng gặp vấn đề tương tự. Tôi có một tệp logging_config.py mà tôi nhập vào tất cả các tệp py khác. Trong tệp logging_config.py, tôi đặt mức ghi nhật ký của trình ghi gốc thành LỖI (theo mặc định là cảnh báo của nó):

logging.basicConfig(
    handlers=[
        RotatingFileHandler('logs.log',maxBytes=1000, backupCount=2),
        logging.StreamHandler(), #print to console
    ],
    level=logging.ERROR
)

Trong các mô-đun khác, tôi nhập logging_config.py và khai báo một trình ghi nhật ký mới và đặt mức của nó thành gỡ lỗi:

log = logging.getLogger(__name__)
log.setLevel(logging.DEBUG)

Bằng cách này, mọi thứ tôi đăng nhập vào tệp py của mình đều được ghi lại, nhưng những thứ được ghi ở cấp gỡ lỗi và thông tin bằng các mô-đun đã nhập như urllib, request, boto3, v.v. không được ghi. Nếu có một số lỗi trong mô-đun nhập đó thì nó đã được ghi lại, vì tôi đã đặt cấp trình ghi gốc thành ERROR.


0

Một điều khác cần xem xét là thuộc tính truyền của lớp Logger.

Ví dụ: thư viện py-suds để xử lý các cuộc gọi xà phòng, thậm chí được đưa vào LỖI

logging.getLogger('suds.client').setLevel(logging.ERROR)
logging.getLogger('suds.transport').setLevel(logging.ERROR)
logging.getLogger('suds.xsdschema').setLevel(logging.ERROR)
logging.getLogger('suds.wsdl').setLevel(logging.ERROR)

ghi nhật ký về một mô-đun có tên sxbasics.py tạo ra một lượng lớn nhật ký

nhập mô tả hình ảnh ở đây

bởi vì việc truyền tải nhật ký là True theo mặc định, đặt thành False, thay vào đó, tôi đã khôi phục 514 MB nhật ký.

import logging
logging.getLogger("suds").propagate = False
logging.getLogger('suds.client').setLevel(logging.ERROR)
logging.getLogger('suds.transport').setLevel(logging.ERROR)
logging.getLogger('suds.xsdschema').setLevel(logging.ERROR)
logging.getLogger('suds.wsdl').setLevel(logging.ERROR)
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.