Tệp nhật ký python trống
Python cung cấp một mô-đun ghi nhật ký tích hợp khá mạnh mẽ và linh hoạt với nhiều tính năng nâng cao. Trong bài viết này, tôi muốn chia sẻ 8 tính năng nâng cao sẽ có lợi cho chúng tôi trong việc phát triển phần mềm Show
Ghi nhật ký 101Trước khi xem xét các tính năng nâng cao hơn, hãy đảm bảo rằng chúng ta đã hiểu cơ bản về mô-đun "%(asctime)s - [%(levelname)s] - %(name)s - (%(filename)s).%(funcName)s(%(lineno)d) - %(message)s"# 2020-07-26 23:37:15,374 - [INFO] - __main__ - (main.py).main(18) - Program starts!4 Tiều phu Phiên bản mà chúng tôi tạo để tạo nhật ký được gọi là logger. Nó được khởi tạo thông qua "%(asctime)s - [%(levelname)s] - %(name)s - (%(filename)s).%(funcName)s(%(lineno)d) - %(message)s"# 2020-07-26 23:37:15,374 - [INFO] - __main__ - (main.py).main(18) - Program starts!5. Cách tốt nhất là sử dụng "%(asctime)s - [%(levelname)s] - %(name)s - (%(filename)s).%(funcName)s(%(lineno)d) - %(message)s"# 2020-07-26 23:37:15,374 - [INFO] - __main__ - (main.py).main(18) - Program starts!6 làm tên nhật ký bao gồm tên gói và tên mô-đun. Tên sẽ xuất hiện trong thông báo nhật ký giúp nhà phát triển nhanh chóng tìm ra nơi tạo nhật ký Trình định dạng & Trình xử lý Mỗi logger có một số cấu hình có thể được sửa đổi. Các cấu hình nâng cao hơn sẽ được thảo luận sau, nhưng những cấu hình phổ biến nhất là trình định dạng và trình xử lý Trình định dạng chỉ định cấu trúc của thông điệp tường trình. Mỗi thông điệp bản ghi là một đối tượng "%(asctime)s - [%(levelname)s] - %(name)s - (%(filename)s).%(funcName)s(%(lineno)d) - %(message)s"# 2020-07-26 23:37:15,374 - [INFO] - __main__ - (main.py).main(18) - Program starts!7 với một số thuộc tính (tên mô-đun là một trong số đó). Khi chúng tôi xác định một trình định dạng, chúng tôi có thể quyết định thông điệp tường trình sẽ trông như thế nào với các thuộc tính này và có thể với các thuộc tính tùy chỉnh. Trình định dạng mặc định trông như thế này severity:logger name:message Một trình định dạng tùy chỉnh với nhiều thuộc tính hơn có thể trông như thế này "%(asctime)s - [%(levelname)s] - %(name)s - (%(filename)s).%(funcName)s(%(lineno)d) - %(message)s"# 2020-07-26 23:37:15,374 - [INFO] - __main__ - (main.py).main(18) - Program starts! Trình xử lý chỉ định đích đến của thông điệp tường trình. Một thông điệp bản ghi có thể được gửi đến nhiều hơn một đích. Mô-đun ghi nhật ký thực sự cung cấp khá nhiều trình xử lý tiêu chuẩn. Những cái phổ biến nhất là FileHandler gửi nhật ký tới một tệp và StreamHandler gửi nhật ký tới các luồng như "%(asctime)s - [%(levelname)s] - %(name)s - (%(filename)s).%(funcName)s(%(lineno)d) - %(message)s"# 2020-07-26 23:37:15,374 - [INFO] - __main__ - (main.py).main(18) - Program starts!8 hoặc "%(asctime)s - [%(levelname)s] - %(name)s - (%(filename)s).%(funcName)s(%(lineno)d) - %(message)s"# 2020-07-26 23:37:15,374 - [INFO] - __main__ - (main.py).main(18) - Program starts!9. Phiên bản nhật ký hỗ trợ 0 hoặc nhiều trình xử lý. Nếu không có trình xử lý nào được xác định, thì nó sẽ gửi nhật ký tới "%(asctime)s - [%(levelname)s] - %(name)s - (%(filename)s).%(funcName)s(%(lineno)d) - %(message)s"# 2020-07-26 23:37:15,374 - [INFO] - __main__ - (main.py).main(18) - Program starts!8. Nếu có nhiều hơn 1 trình xử lý được xác định, thì đích đến phụ thuộc vào cấp độ của thông điệp tường trình và cấp độ của trình xử lý Ví dụ: tôi có Trình xử lý tệp có mức độ CẢNH BÁO và Trình xử lý luồng có mức độ THÔNG TIN. Nếu tôi viết một thông báo nhật ký lỗi thì thông báo đó sẽ được gửi tới cả "%(asctime)s - [%(levelname)s] - %(name)s - (%(filename)s).%(funcName)s(%(lineno)d) - %(message)s"# 2020-07-26 23:37:15,374 - [INFO] - __main__ - (main.py).main(18) - Program starts!0 và tệp nhật ký Thí dụ Trong ví dụ này, chúng tôi đã tạo một "%(asctime)s - [%(levelname)s] - %(name)s - (%(filename)s).%(funcName)s(%(lineno)d) - %(message)s"# 2020-07-26 23:37:15,374 - [INFO] - __main__ - (main.py).main(18) - Program starts!1, "%(asctime)s - [%(levelname)s] - %(name)s - (%(filename)s).%(funcName)s(%(lineno)d) - %(message)s"# 2020-07-26 23:37:15,374 - [INFO] - __main__ - (main.py).main(18) - Program starts!2 và "%(asctime)s - [%(levelname)s] - %(name)s - (%(filename)s).%(funcName)s(%(lineno)d) - %(message)s"# 2020-07-26 23:37:15,374 - [INFO] - __main__ - (main.py).main(18) - Program starts!3. "%(asctime)s - [%(levelname)s] - %(name)s - (%(filename)s).%(funcName)s(%(lineno)d) - %(message)s"# 2020-07-26 23:37:15,374 - [INFO] - __main__ - (main.py).main(18) - Program starts!3 chứa một hàm "%(asctime)s - [%(levelname)s] - %(name)s - (%(filename)s).%(funcName)s(%(lineno)d) - %(message)s"# 2020-07-26 23:37:15,374 - [INFO] - __main__ - (main.py).main(18) - Program starts!5 trả về một phiên bản trình ghi nhật ký. Phiên bản trình ghi nhật ký đi kèm với trình định dạng tùy chỉnh và 2 trình xử lý. StreamHandler với mức INFO và FileHandler với mức WARNING. Điều quan trọng là đặt mức cơ bản thành THÔNG TIN hoặc GỠ LỖI (mức ghi nhật ký mặc định là CẢNH BÁO), nếu không, bất kỳ nhật ký nào thấp hơn mức CẢNH BÁO sẽ bị lọc ra. Cả "%(asctime)s - [%(levelname)s] - %(name)s - (%(filename)s).%(funcName)s(%(lineno)d) - %(message)s"# 2020-07-26 23:37:15,374 - [INFO] - __main__ - (main.py).main(18) - Program starts!1 và "%(asctime)s - [%(levelname)s] - %(name)s - (%(filename)s).%(funcName)s(%(lineno)d) - %(message)s"# 2020-07-26 23:37:15,374 - [INFO] - __main__ - (main.py).main(18) - Program starts!2 tạo đều sử dụng "%(asctime)s - [%(levelname)s] - %(name)s - (%(filename)s).%(funcName)s(%(lineno)d) - %(message)s"# 2020-07-26 23:37:15,374 - [INFO] - __main__ - (main.py).main(18) - Program starts!5 để tạo trình ghi nhật ký của riêng họdiagram Xiaoxu Gaoghi nhật ký cơ bản. py Nhật ký CẢNH BÁO được gửi đến cả đầu ra của bảng điều khiển (sys. thiết bị xuất chuẩn) và tệp nhật ký, nhưng nhật ký INFO chỉ được gửi đến đầu ra của bàn điều khiển. Nếu bạn có thể hiểu đầy đủ những gì đang diễn ra trong ví dụ này và tại sao thì chúng ta nên sử dụng các tính năng nâng cao hơn 1. Tạo các thuộc tính LogRecord do người dùng xác định bằng LoggerAdapterNhư tôi đã đề cập trước đây, LogRecord có một số thuộc tính, các nhà phát triển có thể chọn các thuộc tính quan trọng nhất và đặt chúng vào bộ định dạng. Ngoài ra, mô-đun ghi nhật ký cũng cung cấp khả năng thêm các thuộc tính do người dùng xác định vào LogRecord Một cách là sử dụng "%(asctime)s - [%(levelname)s] - %(name)s - (%(filename)s).%(funcName)s(%(lineno)d) - %(message)s"# 2020-07-26 23:37:15,374 - [INFO] - __main__ - (main.py).main(18) - Program starts!9. Khi bạn tạo một bộ điều hợp, bạn chuyển phiên bản trình ghi nhật ký và các thuộc tính của bạn (trong từ điển) cho nó. Lớp này cung cấp giao diện giống như "%(asctime)s - [%(levelname)s] - %(name)s - (%(filename)s).%(funcName)s(%(lineno)d) - %(message)s"# 2020-07-26 23:37:15,374 - [INFO] - __main__ - (main.py).main(18) - Program starts!20, vì vậy bạn vẫn có thể gọi các phương thức như "%(asctime)s - [%(levelname)s] - %(name)s - (%(filename)s).%(funcName)s(%(lineno)d) - %(message)s"# 2020-07-26 23:37:15,374 - [INFO] - __main__ - (main.py).main(18) - Program starts!21 Thuộc tính mới với giá trị cố định Nếu bạn muốn có một loại thuộc tính giá trị cố định trong thông báo nhật ký, chẳng hạn như tên ứng dụng, thì bạn có thể sử dụng lớp "%(asctime)s - [%(levelname)s] - %(name)s - (%(filename)s).%(funcName)s(%(lineno)d) - %(message)s"# 2020-07-26 23:37:15,374 - [INFO] - __main__ - (main.py).main(18) - Program starts!9 mặc định và nhận giá trị thuộc tính khi bạn tạo trình ghi nhật ký. Đừng quên thêm thuộc tính này vào bộ định dạng, bạn có thể tự do chọn vị trí của nó. Trong đoạn mã sau, tôi thêm thuộc tính "%(asctime)s - [%(levelname)s] - %(name)s - (%(filename)s).%(funcName)s(%(lineno)d) - %(message)s"# 2020-07-26 23:37:15,374 - [INFO] - __main__ - (main.py).main(18) - Program starts!23, giá trị này được xác định khi tôi tạo logger Thuộc tính mới có giá trị động Trong các tình huống khác, bạn có thể muốn các thuộc tính động, chẳng hạn như một loại ID động. Sau đó, bạn có thể mở rộng "%(asctime)s - [%(levelname)s] - %(name)s - (%(filename)s).%(funcName)s(%(lineno)d) - %(message)s"# 2020-07-26 23:37:15,374 - [INFO] - __main__ - (main.py).main(18) - Program starts!9 cơ bản và tạo của riêng mình. Phương thức "%(asctime)s - [%(levelname)s] - %(name)s - (%(filename)s).%(funcName)s(%(lineno)d) - %(message)s"# 2020-07-26 23:37:15,374 - [INFO] - __main__ - (main.py).main(18) - Program starts!25 là nơi các thuộc tính bổ sung được thêm vào thông điệp tường trình. Trong đoạn mã sau, tôi thêm một thuộc tính động "%(asctime)s - [%(levelname)s] - %(name)s - (%(filename)s).%(funcName)s(%(lineno)d) - %(message)s"# 2020-07-26 23:37:15,374 - [INFO] - __main__ - (main.py).main(18) - Program starts!26, thuộc tính này có thể khác nhau trong mỗi thông báo tường trình. Trong trường hợp này, bạn không cần thêm thuộc tính vào bộ định dạnggiá trị động của bộ điều hợp ghi nhật ký. py 2. Tạo thuộc tính LogRecord do người dùng xác định bằng Bộ lọcMột cách khác để thêm các thuộc tính động do người dùng xác định là sử dụng Bộ lọc tùy chỉnh. Bộ lọc cung cấp logic bổ sung để xác định thông điệp nhật ký nào sẽ xuất ra. Đây là một bước sau khi kiểm tra mức ghi nhật ký cơ bản, nhưng trước khi chuyển thông báo tường trình tới trình xử lý. Ngoài việc xác định xem thông điệp bản ghi có nên tiếp tục hay không, chúng ta cũng có thể chèn các thuộc tính mới vào phương thức "%(asctime)s - [%(levelname)s] - %(name)s - (%(filename)s).%(funcName)s(%(lineno)d) - %(message)s"# 2020-07-26 23:37:15,374 - [INFO] - __main__ - (main.py).main(18) - Program starts!27sơ đồ từ tài liệu chính thức của Python Trong ví dụ này, chúng tôi thêm một thuộc tính mới "%(asctime)s - [%(levelname)s] - %(name)s - (%(filename)s).%(funcName)s(%(lineno)d) - %(message)s"# 2020-07-26 23:37:15,374 - [INFO] - __main__ - (main.py).main(18) - Program starts!28 trong "%(asctime)s - [%(levelname)s] - %(name)s - (%(filename)s).%(funcName)s(%(lineno)d) - %(message)s"# 2020-07-26 23:37:15,374 - [INFO] - __main__ - (main.py).main(18) - Program starts!27 có giá trị được xác định dựa trên tên cấp độ của thông điệp tường trình. Trong trường hợp này, nên thêm lại tên thuộc tính vào bộ định dạngthuộc tính động của bộ lọc ghi nhật ký. py 3. Đa luồng với mô-đun ghi nhật kýMô-đun ghi nhật ký thực sự được triển khai theo cách an toàn cho luồng, vì vậy chúng tôi không cần nỗ lực thêm. Đoạn mã dưới đây cho thấy MainThread và WorkThread đang chia sẻ cùng một phiên bản trình ghi nhật ký mà không gặp vấn đề về tình trạng tương tranh. Ngoài ra còn có một thuộc tính tích hợp sẵn "%(asctime)s - [%(levelname)s] - %(name)s - (%(filename)s).%(funcName)s(%(lineno)d) - %(message)s"# 2020-07-26 23:37:15,374 - [INFO] - __main__ - (main.py).main(18) - Program starts!40 cho trình định dạngđăng nhập đa luồng. py Về cơ bản, mô-đun ghi nhật ký sử dụng "%(asctime)s - [%(levelname)s] - %(name)s - (%(filename)s).%(funcName)s(%(lineno)d) - %(message)s"# 2020-07-26 23:37:15,374 - [INFO] - __main__ - (main.py).main(18) - Program starts!41 khá nhiều ở mọi nơi. Sự khác biệt giữa "%(asctime)s - [%(levelname)s] - %(name)s - (%(filename)s).%(funcName)s(%(lineno)d) - %(message)s"# 2020-07-26 23:37:15,374 - [INFO] - __main__ - (main.py).main(18) - Program starts!42 từ "%(asctime)s - [%(levelname)s] - %(name)s - (%(filename)s).%(funcName)s(%(lineno)d) - %(message)s"# 2020-07-26 23:37:15,374 - [INFO] - __main__ - (main.py).main(18) - Program starts!43 là
Bất kỳ trình xử lý nào mở rộng từ lớp "%(asctime)s - [%(levelname)s] - %(name)s - (%(filename)s).%(funcName)s(%(lineno)d) - %(message)s"# 2020-07-26 23:37:15,374 - [INFO] - __main__ - (main.py).main(18) - Program starts!48 đều có phương thức "%(asctime)s - [%(levelname)s] - %(name)s - (%(filename)s).%(funcName)s(%(lineno)d) - %(message)s"# 2020-07-26 23:37:15,374 - [INFO] - __main__ - (main.py).main(18) - Program starts!49 để gửi bản ghi. Đây là một khối mã của "%(asctime)s - [%(levelname)s] - %(name)s - (%(filename)s).%(funcName)s(%(lineno)d) - %(message)s"# 2020-07-26 23:37:15,374 - [INFO] - __main__ - (main.py).main(18) - Program starts!50. Như bạn có thể thấy, trình xử lý sẽ nhận và giải phóng khóa trước và sau khi gửi bản ghi. Phương pháp "%(asctime)s - [%(levelname)s] - %(name)s - (%(filename)s).%(funcName)s(%(lineno)d) - %(message)s"# 2020-07-26 23:37:15,374 - [INFO] - __main__ - (main.py).main(18) - Program starts!51 có thể được triển khai khác nhau trong các trình xử lý khác nhauxử lý. py 4. Đa xử lý với mô-đun ghi nhật ký — QueueHandlerMặc dù mô-đun ghi nhật ký an toàn cho luồng nhưng không an toàn cho quy trình. Nếu bạn muốn nhiều quy trình ghi vào cùng một tệp nhật ký, thì bạn phải quản lý quyền truy cập vào tệp của mình theo cách thủ công. Theo nhật ký Cookbook, có một số tùy chọn QueueHandler + quy trình “người tiêu dùng” Một tùy chọn đang sử dụng "%(asctime)s - [%(levelname)s] - %(name)s - (%(filename)s).%(funcName)s(%(lineno)d) - %(message)s"# 2020-07-26 23:37:15,374 - [INFO] - __main__ - (main.py).main(18) - Program starts!52. Ý tưởng là tạo một phiên bản "%(asctime)s - [%(levelname)s] - %(name)s - (%(filename)s).%(funcName)s(%(lineno)d) - %(message)s"# 2020-07-26 23:37:15,374 - [INFO] - __main__ - (main.py).main(18) - Program starts!53 và chia sẻ nó giữa nhiều quy trình. Trong ví dụ bên dưới, chúng tôi có 2 quy trình "nhà sản xuất" gửi nhật ký đến hàng đợi và quy trình "người tiêu dùng" đọc nhật ký từ hàng đợi và ghi chúng vào tệp nhật ký Nhật ký trong hàng đợi có thể sẽ có các cấp độ khác nhau, do đó trong "%(asctime)s - [%(levelname)s] - %(name)s - (%(filename)s).%(funcName)s(%(lineno)d) - %(message)s"# 2020-07-26 23:37:15,374 - [INFO] - __main__ - (main.py).main(18) - Program starts!54, chúng tôi sử dụng "%(asctime)s - [%(levelname)s] - %(name)s - (%(filename)s).%(funcName)s(%(lineno)d) - %(message)s"# 2020-07-26 23:37:15,374 - [INFO] - __main__ - (main.py).main(18) - Program starts!55 thay vì "%(asctime)s - [%(levelname)s] - %(name)s - (%(filename)s).%(funcName)s(%(lineno)d) - %(message)s"# 2020-07-26 23:37:15,374 - [INFO] - __main__ - (main.py).main(18) - Program starts!56 hoặc "%(asctime)s - [%(levelname)s] - %(name)s - (%(filename)s).%(funcName)s(%(lineno)d) - %(message)s"# 2020-07-26 23:37:15,374 - [INFO] - __main__ - (main.py).main(18) - Program starts!57. Cuối cùng, chúng tôi gửi tín hiệu để cho "%(asctime)s - [%(levelname)s] - %(name)s - (%(filename)s).%(funcName)s(%(lineno)d) - %(message)s"# 2020-07-26 23:37:15,374 - [INFO] - __main__ - (main.py).main(18) - Program starts!54 dừng lại. Chia sẻ một phiên bản hàng đợi giữa nhiều quy trình hoặc luồng không phải là một điều mới, nhưng các loại mô-đun ghi nhật ký giúp chúng tôi xử lý tình huống này QueueHandler + QueueListener Trong mô-đun "%(asctime)s - [%(levelname)s] - %(name)s - (%(filename)s).%(funcName)s(%(lineno)d) - %(message)s"# 2020-07-26 23:37:15,374 - [INFO] - __main__ - (main.py).main(18) - Program starts!59, có một lớp đặc biệt gọi là "%(asctime)s - [%(levelname)s] - %(name)s - (%(filename)s).%(funcName)s(%(lineno)d) - %(message)s"# 2020-07-26 23:37:15,374 - [INFO] - __main__ - (main.py).main(18) - Program starts!60. Lớp này tạo một phiên bản trình nghe với hàng đợi thông điệp tường trình và danh sách các trình xử lý để xử lý các bản ghi nhật ký. "%(asctime)s - [%(levelname)s] - %(name)s - (%(filename)s).%(funcName)s(%(lineno)d) - %(message)s"# 2020-07-26 23:37:15,374 - [INFO] - __main__ - (main.py).main(18) - Program starts!61 có thể thay thế quy trình "%(asctime)s - [%(levelname)s] - %(name)s - (%(filename)s).%(funcName)s(%(lineno)d) - %(message)s"# 2020-07-26 23:37:15,374 - [INFO] - __main__ - (main.py).main(18) - Program starts!62 mà chúng ta đã tạo trong ví dụ trước với ít mã hơnngười nghe hàng đợi đăng nhập. py SocketHandler Một giải pháp khác do Cookbook cung cấp là gửi nhật ký từ nhiều quy trình đến "%(asctime)s - [%(levelname)s] - %(name)s - (%(filename)s).%(funcName)s(%(lineno)d) - %(message)s"# 2020-07-26 23:37:15,374 - [INFO] - __main__ - (main.py).main(18) - Program starts!63 và có một quy trình riêng triển khai máy chủ ổ cắm đọc nhật ký và gửi đến đích. Văn bản có cách thực hiện khá chi tiết Tất cả các giải pháp này về cơ bản đều tuân theo cùng một nguyên tắc. gửi nhật ký từ các quy trình khác nhau đến một nơi tập trung, hàng đợi hoặc máy chủ từ xa. Người nhận ở phía bên kia chịu trách nhiệm ghi các bản ghi nhật ký vào các đích 5. Không phát ra bất kỳ nhật ký thư viện nào theo mặc định — NullHandlerCho đến nay, chúng tôi đã đề cập đến một số trình xử lý được triển khai bởi mô-đun ghi nhật ký. Một trình xử lý tích hợp hữu ích khác là "%(asctime)s - [%(levelname)s] - %(name)s - (%(filename)s).%(funcName)s(%(lineno)d) - %(message)s"# 2020-07-26 23:37:15,374 - [INFO] - __main__ - (main.py).main(18) - Program starts!64. Việc triển khai NullHandler về cơ bản không có gì. Tuy nhiên, nó giúp các nhà phát triển phân biệt nhật ký thư viện với nhật ký ứng dụng Đây là triển khai của "%(asctime)s - [%(levelname)s] - %(name)s - (%(filename)s).%(funcName)s(%(lineno)d) - %(message)s"# 2020-07-26 23:37:15,374 - [INFO] - __main__ - (main.py).main(18) - Program starts!65nullhandler. py Tại sao chúng ta cần phân biệt nhật ký thư viện với nhật ký ứng dụng? Theo tác giả của mô-đun ghi nhật ký, Vinay Sajip
Cách tốt nhất là không phát ra nhật ký thư viện theo mặc định và để người dùng thư viện xác định xem họ có muốn nhận và xử lý nhật ký trong ứng dụng hay không Là nhà phát triển thư viện, chúng tôi chỉ cần một dòng mã bên trong "%(asctime)s - [%(levelname)s] - %(name)s - (%(filename)s).%(funcName)s(%(lineno)d) - %(message)s"# 2020-07-26 23:37:15,374 - [INFO] - __main__ - (main.py).main(18) - Program starts!67 để thêm "%(asctime)s - [%(levelname)s] - %(name)s - (%(filename)s).%(funcName)s(%(lineno)d) - %(message)s"# 2020-07-26 23:37:15,374 - [INFO] - __main__ - (main.py).main(18) - Program starts!65. Trong các gói con và mô-đun con, bộ ghi nhật ký vẫn như bình thường. Khi chúng tôi cài đặt gói này trong ứng dụng của mình qua "%(asctime)s - [%(levelname)s] - %(name)s - (%(filename)s).%(funcName)s(%(lineno)d) - %(message)s"# 2020-07-26 23:37:15,374 - [INFO] - __main__ - (main.py).main(18) - Program starts!69, chúng tôi sẽ không thấy nhật ký từ thư viện theo mặc địnhđăng nhập ví dụ nullhandler. py Cách để hiển thị các nhật ký này là thêm trình xử lý vào trình ghi nhật ký thư viện trong ứng dụng của bạn "%(asctime)s - [%(levelname)s] - %(name)s - (%(filename)s).%(funcName)s(%(lineno)d) - %(message)s"# 2020-07-26 23:37:15,374 - [INFO] - __main__ - (main.py).main(18) - Program starts!2 Nếu thư viện không sử dụng "%(asctime)s - [%(levelname)s] - %(name)s - (%(filename)s).%(funcName)s(%(lineno)d) - %(message)s"# 2020-07-26 23:37:15,374 - [INFO] - __main__ - (main.py).main(18) - Program starts!65, nhưng bạn muốn tắt nhật ký thư viện, thì bạn có thể đặt "%(asctime)s - [%(levelname)s] - %(name)s - (%(filename)s).%(funcName)s(%(lineno)d) - %(message)s"# 2020-07-26 23:37:15,374 - [INFO] - __main__ - (main.py).main(18) - Program starts!71. Nếu tuyên truyền được đặt thành Sai, thì nhật ký sẽ không được chuyển đến trình xử lý 6. Xoay các tệp nhật ký của bạn — RotatingFileHandler, TimedRotatingFileHandler"%(asctime)s - [%(levelname)s] - %(name)s - (%(filename)s).%(funcName)s(%(lineno)d) - %(message)s"# 2020-07-26 23:37:15,374 - [INFO] - __main__ - (main.py).main(18) - Program starts!72 hỗ trợ xoay tệp nhật ký, giúp trình xử lý có khả năng xoay tệp nhật ký dựa trên kích thước tối đa của nó. 2 tham số nên được xác định ở đây. maxBytes và backupCount. maxBytes cho trình xử lý biết khi nào xoay nhật ký. backupCount là số lượng tệp nhật ký, mỗi tệp nhật ký mở rộng có hậu tố “. 1”, “. 2” ở cuối tên tệp. Nếu thông báo nhật ký hiện tại sắp cho phép tệp nhật ký vượt quá kích thước tối đa, thì trình xử lý sẽ đóng tệp hiện tại và mở tệp tiếp theo Đây là một ví dụ rất giống với Cookbook. Bạn sẽ nhận được 6 tệp nhật ký Một trình xử lý xoay tệp khác là "%(asctime)s - [%(levelname)s] - %(name)s - (%(filename)s).%(funcName)s(%(lineno)d) - %(message)s"# 2020-07-26 23:37:15,374 - [INFO] - __main__ - (main.py).main(18) - Program starts!73, cho phép nhà phát triển tạo nhật ký xoay vòng dựa trên thời gian đã trôi qua. Điều kiện về thời gian bao gồm. giây, phút, giờ, ngày, w0-w6 (0=thứ Hai) và nửa đêm (chuyển hạn lúc nửa đêm) Trong ví dụ sau, chúng tôi xoay tệp nhật ký mỗi giây với 5 tệp sao lưu. Mỗi tệp sao lưu có dấu thời gian làm hậu tố xoay vòng tập tin thời gian. py7. Ngoại lệ trong quá trình đăng nhậpTrong nhiều trường hợp, chúng tôi sử dụng "%(asctime)s - [%(levelname)s] - %(name)s - (%(filename)s).%(funcName)s(%(lineno)d) - %(message)s"# 2020-07-26 23:37:15,374 - [INFO] - __main__ - (main.py).main(18) - Program starts!74 hoặc "%(asctime)s - [%(levelname)s] - %(name)s - (%(filename)s).%(funcName)s(%(lineno)d) - %(message)s"# 2020-07-26 23:37:15,374 - [INFO] - __main__ - (main.py).main(18) - Program starts!75 khi xử lý các trường hợp ngoại lệ. Nhưng nếu logger tự đưa ra một ngoại lệ, điều gì sẽ xảy ra với chương trình? Lỗi logger được xử lý khi trình xử lý gọi "%(asctime)s - [%(levelname)s] - %(name)s - (%(filename)s).%(funcName)s(%(lineno)d) - %(message)s"# 2020-07-26 23:37:15,374 - [INFO] - __main__ - (main.py).main(18) - Program starts!51, có nghĩa là bất kỳ ngoại lệ nào liên quan đến định dạng hoặc viết đều bị trình xử lý bắt thay vì được nêu ra. Cụ thể hơn, phương thức "%(asctime)s - [%(levelname)s] - %(name)s - (%(filename)s).%(funcName)s(%(lineno)d) - %(message)s"# 2020-07-26 23:37:15,374 - [INFO] - __main__ - (main.py).main(18) - Program starts!77 sẽ in ra trackback tới "%(asctime)s - [%(levelname)s] - %(name)s - (%(filename)s).%(funcName)s(%(lineno)d) - %(message)s"# 2020-07-26 23:37:15,374 - [INFO] - __main__ - (main.py).main(18) - Program starts!78 và chương trình sẽ tiếp tục. Nếu bạn có một trình xử lý tùy chỉnh mở rộng từ lớp "%(asctime)s - [%(levelname)s] - %(name)s - (%(filename)s).%(funcName)s(%(lineno)d) - %(message)s"# 2020-07-26 23:37:15,374 - [INFO] - __main__ - (main.py).main(18) - Program starts!48, bạn có thể triển khai lớp "%(asctime)s - [%(levelname)s] - %(name)s - (%(filename)s).%(funcName)s(%(lineno)d) - %(message)s"# 2020-07-26 23:37:15,374 - [INFO] - __main__ - (main.py).main(18) - Program starts!77 của riêng mình Trong ví dụ này, thông điệp tường trình thứ hai có quá nhiều đối số. Vì vậy, trong đầu ra của bảng điều khiển, chúng tôi đã nhận được trackback và chương trình vẫn có thể tiếp tục Tuy nhiên, nếu ngoại lệ xảy ra bên ngoài "%(asctime)s - [%(levelname)s] - %(name)s - (%(filename)s).%(funcName)s(%(lineno)d) - %(message)s"# 2020-07-26 23:37:15,374 - [INFO] - __main__ - (main.py).main(18) - Program starts!51, thì ngoại lệ đó có thể được nêu ra và chương trình sẽ dừng lại. Ví dụ: trong mã bên dưới, chúng tôi thêm một thuộc tính bổ sung "%(asctime)s - [%(levelname)s] - %(name)s - (%(filename)s).%(funcName)s(%(lineno)d) - %(message)s"# 2020-07-26 23:37:15,374 - [INFO] - __main__ - (main.py).main(18) - Program starts!26 trong "%(asctime)s - [%(levelname)s] - %(name)s - (%(filename)s).%(funcName)s(%(lineno)d) - %(message)s"# 2020-07-26 23:37:15,374 - [INFO] - __main__ - (main.py).main(18) - Program starts!56 mà không xử lý nó trong LoggerAdapter. Lỗi này không được xử lý và khiến chương trình dừng lạităng ngoại lệ đăng nhập. py 8. 3 cách khác nhau để định cấu hình bộ ghi của bạnĐiểm cuối cùng tôi muốn chia sẻ là về cấu hình logger của bạn. Có 3 cách để cấu hình một logger sử dụng mã Tùy chọn đơn giản nhất là sử dụng mã để định cấu hình bộ ghi của bạn, giống như tất cả các ví dụ mà chúng tôi đã thấy cho đến nay trong bài viết này. Nhưng nhược điểm của tùy chọn này là mọi sửa đổi đều yêu cầu thay đổi mã nguồn sử dụng "%(asctime)s - [%(levelname)s] - %(name)s - (%(filename)s).%(funcName)s(%(lineno)d) - %(message)s"# 2020-07-26 23:37:15,374 - [INFO] - __main__ - (main.py).main(18) - Program starts!84 Tùy chọn thứ hai là viết cấu hình trong từ điển và sử dụng "%(asctime)s - [%(levelname)s] - %(name)s - (%(filename)s).%(funcName)s(%(lineno)d) - %(message)s"# 2020-07-26 23:37:15,374 - [INFO] - __main__ - (main.py).main(18) - Program starts!85 để đọc nó. Bạn cũng có thể lưu từ điển vào tệp JSON và đọc từ đó. Ưu điểm là nó có thể được tải như một cấu hình bên ngoài, nhưng nó có thể dễ bị lỗi do cấu trúc của nóđăng nhập cấu hình json. py sử dụng "%(asctime)s - [%(levelname)s] - %(name)s - (%(filename)s).%(funcName)s(%(lineno)d) - %(message)s"# 2020-07-26 23:37:15,374 - [INFO] - __main__ - (main.py).main(18) - Program starts!86 Cuối cùng nhưng không kém phần quan trọng, tùy chọn thứ ba là sử dụng "%(asctime)s - [%(levelname)s] - %(name)s - (%(filename)s).%(funcName)s(%(lineno)d) - %(message)s"# 2020-07-26 23:37:15,374 - [INFO] - __main__ - (main.py).main(18) - Program starts!87. Cấu hình được ghi vào một tệp "%(asctime)s - [%(levelname)s] - %(name)s - (%(filename)s).%(funcName)s(%(lineno)d) - %(message)s"# 2020-07-26 23:37:15,374 - [INFO] - __main__ - (main.py).main(18) - Program starts!88 riêngđăng nhập tập tin cấu hình. py Có thể cập nhật cấu hình trong thời gian chạy thông qua máy chủ cấu hình. Cookbook hiển thị một ví dụ về cả phía máy khách và phía máy chủ. Cấu hình được cập nhật thông qua kết nối ổ cắm và ở phía máy khách, chúng tôi sử dụng "%(asctime)s - [%(levelname)s] - %(name)s - (%(filename)s).%(funcName)s(%(lineno)d) - %(message)s"# 2020-07-26 23:37:15,374 - [INFO] - __main__ - (main.py).main(18) - Program starts!89 để nhận cấu hình mới nhất Tôi hy vọng những mẹo và thủ thuật ghi nhật ký này có thể giúp bạn thiết lập một khung ghi nhật ký tốt xung quanh ứng dụng của mình mà không ảnh hưởng đến hiệu suất. Nếu có gì muốn chia sẻ hãy để lại bình luận bên dưới |