Gói Stdlib
import logging
import sys
logger = logging.getLogger["pylog"]
logger.setLevel[logging.DEBUG]
h2 = logging.FileHandler[filename="/tmp/records.log"]
h2.setLevel[logging.INFO]
h2 = logging.StreamHandler[sys.stderr]
h2.setLevel[logging.ERROR]
logger.addHandler[h2]
logger.addHandler[h2]
logger.info["testing %d.. %d.. %d..", 1, 2, 3]
5 cung cấp rất nhiều tính linh hoạt và chức năng cho các nhà phát triển / DevOps / nhân viên hỗ trợ, và sự linh hoạt đó có một số chi phí, rõ ràng. Nếu nhu cầu về hiệu suất vượt qua sự cần thiết phải linh hoạt, bạn cần phải đi với một thứ khác. Bạn đã thực hiện các bước để tối ưu hóa mô tả trong tài liệu? Một cuộc gọi ghi nhật ký điển hình theo thứ tự hàng chục micro giây trên phần cứng hợp lý, điều mà hầu như không có vẻ quá mức. Tuy nhiên, việc đăng nhập vào các vòng lặp chặt chẽ hiếm khi được khuyến khích, nếu chỉ vì lượng thông tin được tạo ra có thể mất quá nhiều thời gian để lội qua.Mã để tìm người gọi có thể khá đắt, nhưng là cần thiết nếu bạn muốn, ví dụ: Tên tệp và số dòng nơi thực hiện cuộc gọi ghi nhật ký.
import logging
import sys
logger = logging.getLogger["pylog"]
logger.setLevel[logging.DEBUG]
h2 = logging.FileHandler[filename="/tmp/records.log"]
h2.setLevel[logging.INFO]
h2 = logging.StreamHandler[sys.stderr]
h2.setLevel[logging.ERROR]
logger.addHandler[h2]
logger.addHandler[h2]
logger.info["testing %d.. %d.. %d..", 1, 2, 3]
6 được dành cho các kịch bản trong đó I/O khai thác sẽ mất thời gian đáng kể và không thể thực hiện theo băng tần. Ví dụ: một ứng dụng web có nhật ký cần được gửi qua email cho quản trị viên trang web không thể rủi ro bằng cách sử dụng trực tiếp import logging
import sys
logger = logging.getLogger["pylog"]
logger.setLevel[logging.DEBUG]
h2 = logging.FileHandler[filename="/tmp/records.log"]
h2.setLevel[logging.INFO]
h2 = logging.StreamHandler[sys.stderr]
h2.setLevel[logging.ERROR]
logger.addHandler[h2]
logger.addHandler[h2]
logger.info["testing %d.. %d.. %d..", 1, 2, 3]
7, vì cái bắt tay email có thể chậm.Đừng quên rằng việc chuyển đổi ngữ cảnh trong Python là chậm. Bạn đã thử
import logging
import sys
logger = logging.getLogger["pylog"]
logger.setLevel[logging.DEBUG]
h2 = logging.FileHandler[filename="/tmp/records.log"]
h2.setLevel[logging.INFO]
h2 = logging.StreamHandler[sys.stderr]
h2.setLevel[logging.ERROR]
logger.addHandler[h2]
logger.addHandler[h2]
logger.info["testing %d.. %d.. %d..", 1, 2, 3]
8 chưa? Có một điểm bắt đầu phù hợp trong tài liệu cho một quy trình nhận riêng thực hiện I/O thực tế để nộp, email, v.v. để quy trình của bạn chỉ thực hiện ổ cắm I/O và không thực hiện chuyển đổi ngữ cảnh chỉ để ghi nhật ký. Và sử dụng ổ cắm tên miền hoặc UDP có thể vẫn nhanh hơn, mặc dù sau đó là mất mát.Có nhiều cách khác để tối ưu hóa. Ví dụ, các trình xử lý tiêu chuẩn trong việc ghi nhật ký làm khóa xung quanh
import logging
import sys
logger = logging.getLogger["pylog"]
logger.setLevel[logging.DEBUG]
h2 = logging.FileHandler[filename="/tmp/records.log"]
h2.setLevel[logging.INFO]
h2 = logging.StreamHandler[sys.stderr]
h2.setLevel[logging.ERROR]
logger.addHandler[h2]
logger.addHandler[h2]
logger.info["testing %d.. %d.. %d..", 1, 2, 3]
9, đối với an toàn chủ đề - nếu trong một kịch bản cụ thể dưới sự kiểm soát của bạn, không có sự tranh chấp nào đối với người xử lý, bạn có thể có một lớp con xử lý không thu nhận và phát hành khóa. Và như thế. Gói Python
import logging
import sys
logger = logging.getLogger["pylog"]
logger.setLevel[logging.DEBUG]
h2 = logging.FileHandler[filename="/tmp/records.log"]
h2.setLevel[logging.INFO]
h2 = logging.StreamHandler[sys.stderr]
h2.setLevel[logging.ERROR]
logger.addHandler[h2]
logger.addHandler[h2]
logger.info["testing %d.. %d.. %d..", 1, 2, 3]
5 là một gói nhẹ nhưng có thể mở rộng để theo dõi tốt hơn những gì mã của bạn làm. Sử dụng nó mang lại cho bạn sự linh hoạt hơn nhiều so với việc chỉ xả mã của bạn bằng các cuộc gọi >>> import logging
>>> import pdb
>>> def f[x]:
... logging.error["bad vibes"]
... return x / 0
...
>>> pdb.run["f[1]"]
1 thừa.Tuy nhiên, gói Python từ
import logging
import sys
logger = logging.getLogger["pylog"]
logger.setLevel[logging.DEBUG]
h2 = logging.FileHandler[filename="/tmp/records.log"]
h2.setLevel[logging.INFO]
h2 = logging.StreamHandler[sys.stderr]
h2.setLevel[logging.ERROR]
logger.addHandler[h2]
logger.addHandler[h2]
logger.info["testing %d.. %d.. %d..", 1, 2, 3]
5 có thể phức tạp ở một số điểm nhất định. Trình xử lý, logger, cấp độ, không gian tên, bộ lọc: Nó không dễ để theo dõi tất cả các phần này và cách chúng tương tác.Một cách để buộc các kết thúc lỏng lẻo trong sự hiểu biết của bạn về
import logging
import sys
logger = logging.getLogger["pylog"]
logger.setLevel[logging.DEBUG]
h2 = logging.FileHandler[filename="/tmp/records.log"]
h2.setLevel[logging.INFO]
h2 = logging.StreamHandler[sys.stderr]
h2.setLevel[logging.ERROR]
logger.addHandler[h2]
logger.addHandler[h2]
logger.info["testing %d.. %d.. %d..", 1, 2, 3]
5 là nhìn trộm dưới mui xe vào mã nguồn cpython của nó. Mã Python đằng sau import logging
import sys
logger = logging.getLogger["pylog"]
logger.setLevel[logging.DEBUG]
h2 = logging.FileHandler[filename="/tmp/records.log"]
h2.setLevel[logging.INFO]
h2 = logging.StreamHandler[sys.stderr]
h2.setLevel[logging.ERROR]
logger.addHandler[h2]
logger.addHandler[h2]
logger.info["testing %d.. %d.. %d..", 1, 2, 3]
5 là súc tích và mô -đun, và đọc qua nó có thể giúp bạn có được khoảnh khắc đó.Bài viết này có nghĩa là để bổ sung cho việc ghi nhật ký tài liệu cũng như đăng nhập vào Python, đây là một hướng dẫn về cách sử dụng gói.
Đến cuối bài viết này, bạn sẽ quen thuộc với những điều sau đây::
5 cấp độ và cách chúng hoạt độngimport logging import sys logger = logging.getLogger["pylog"] logger.setLevel[logging.DEBUG] h2 = logging.FileHandler[filename="/tmp/records.log"] h2.setLevel[logging.INFO] h2 = logging.StreamHandler[sys.stderr] h2.setLevel[logging.ERROR] logger.addHandler[h2] logger.addHandler[h2] logger.info["testing %d.. %d.. %d..", 1, 2, 3]
- Thread-Safety so với Process-Safety trong
5import logging import sys logger = logging.getLogger["pylog"] logger.setLevel[logging.DEBUG] h2 = logging.FileHandler[filename="/tmp/records.log"] h2.setLevel[logging.INFO] h2 = logging.StreamHandler[sys.stderr] h2.setLevel[logging.ERROR] logger.addHandler[h2] logger.addHandler[h2] logger.info["testing %d.. %d.. %d..", 1, 2, 3]
- Thiết kế của
5 từ góc độ OOPimport logging import sys logger = logging.getLogger["pylog"] logger.setLevel[logging.DEBUG] h2 = logging.FileHandler[filename="/tmp/records.log"] h2.setLevel[logging.INFO] h2 = logging.StreamHandler[sys.stderr] h2.setLevel[logging.ERROR] logger.addHandler[h2] logger.addHandler[h2] logger.info["testing %d.. %d.. %d..", 1, 2, 3]
- Đăng nhập thư viện so với các ứng dụng
- Thực tiễn và mô hình thiết kế tốt nhất để sử dụng
5import logging import sys logger = logging.getLogger["pylog"] logger.setLevel[logging.DEBUG] h2 = logging.FileHandler[filename="/tmp/records.log"] h2.setLevel[logging.INFO] h2 = logging.StreamHandler[sys.stderr] h2.setLevel[logging.ERROR] logger.addHandler[h2] logger.addHandler[h2] logger.info["testing %d.. %d.. %d..", 1, 2, 3]
Đối với hầu hết các phần, chúng tôi sẽ đi theo mô-đun cốt lõi trong gói Python, ____ ____55 để xây dựng một bức tranh về cách mà nó đặt ra.
Làm thế nào để theo dõi
Bởi vì mã nguồn
import logging
import sys
logger = logging.getLogger["pylog"]
logger.setLevel[logging.DEBUG]
h2 = logging.FileHandler[filename="/tmp/records.log"]
h2.setLevel[logging.INFO]
h2 = logging.StreamHandler[sys.stderr]
h2.setLevel[logging.ERROR]
logger.addHandler[h2]
logger.addHandler[h2]
logger.info["testing %d.. %d.. %d..", 1, 2, 3]
5 là trung tâm của bài viết này, bạn có thể giả sử rằng bất kỳ khối mã hoặc liên kết nào cũng dựa trên một cam kết cụ thể trong kho lưu trữ CPython Python 3.7, cụ thể là cam kết [Pdb] l
1514 exc_info = [type[exc_info], exc_info, exc_info.__traceback__]
1515 elif not isinstance[exc_info, tuple]:
1516 exc_info = sys.exc_info[]
1517 record = self.makeRecord[self.name, level, fn, lno, msg, args,
1518 exc_info, func, extra, sinfo]
1519 -> self.handle[record]
1520
1521 def handle[self, record]:
1522 """
1523 Call the handlers for the specified record.
1524
[Pdb] from pprint import pprint
[Pdb] pprint[vars[record]]
{'args': [],
'created': 1550671851.660067,
'exc_info': None,
'exc_text': None,
'filename': '',
'funcName': 'f',
'levelname': 'ERROR',
'levelno': 40,
'lineno': 2,
'module': '',
'msecs': 660.067081451416,
'msg': 'bad vibes',
'name': 'root',
'pathname': '',
'process': 2360,
'processName': 'MainProcess',
'relativeCreated': 295145.5490589142,
'stack_info': None,
'thread': 4372293056,
'threadName': 'MainThread'}
1. Bạn có thể tìm thấy gói import logging
import sys
logger = logging.getLogger["pylog"]
logger.setLevel[logging.DEBUG]
h2 = logging.FileHandler[filename="/tmp/records.log"]
h2.setLevel[logging.INFO]
h2 = logging.StreamHandler[sys.stderr]
h2.setLevel[logging.ERROR]
logger.addHandler[h2]
logger.addHandler[h2]
logger.info["testing %d.. %d.. %d..", 1, 2, 3]
5 trong thư mục [Pdb] l
1514 exc_info = [type[exc_info], exc_info, exc_info.__traceback__]
1515 elif not isinstance[exc_info, tuple]:
1516 exc_info = sys.exc_info[]
1517 record = self.makeRecord[self.name, level, fn, lno, msg, args,
1518 exc_info, func, extra, sinfo]
1519 -> self.handle[record]
1520
1521 def handle[self, record]:
1522 """
1523 Call the handlers for the specified record.
1524
[Pdb] from pprint import pprint
[Pdb] pprint[vars[record]]
{'args': [],
'created': 1550671851.660067,
'exc_info': None,
'exc_text': None,
'filename': '',
'funcName': 'f',
'levelname': 'ERROR',
'levelno': 40,
'lineno': 2,
'module': '',
'msecs': 660.067081451416,
'msg': 'bad vibes',
'name': 'root',
'pathname': '',
'process': 2360,
'processName': 'MainProcess',
'relativeCreated': 295145.5490589142,
'stack_info': None,
'thread': 4372293056,
'threadName': 'MainThread'}
3 trong nguồn cpython.Trong gói
import logging
import sys
logger = logging.getLogger["pylog"]
logger.setLevel[logging.DEBUG]
h2 = logging.FileHandler[filename="/tmp/records.log"]
h2.setLevel[logging.INFO]
h2 = logging.StreamHandler[sys.stderr]
h2.setLevel[logging.ERROR]
logger.addHandler[h2]
logger.addHandler[h2]
logger.info["testing %d.. %d.. %d..", 1, 2, 3]
5, hầu hết các lần nâng nặng xảy ra trong [Pdb] l
1514 exc_info = [type[exc_info], exc_info, exc_info.__traceback__]
1515 elif not isinstance[exc_info, tuple]:
1516 exc_info = sys.exc_info[]
1517 record = self.makeRecord[self.name, level, fn, lno, msg, args,
1518 exc_info, func, extra, sinfo]
1519 -> self.handle[record]
1520
1521 def handle[self, record]:
1522 """
1523 Call the handlers for the specified record.
1524
[Pdb] from pprint import pprint
[Pdb] pprint[vars[record]]
{'args': [],
'created': 1550671851.660067,
'exc_info': None,
'exc_text': None,
'filename': '',
'funcName': 'f',
'levelname': 'ERROR',
'levelno': 40,
'lineno': 2,
'module': '',
'msecs': 660.067081451416,
'msg': 'bad vibes',
'name': 'root',
'pathname': '',
'process': 2360,
'processName': 'MainProcess',
'relativeCreated': 295145.5490589142,
'stack_info': None,
'thread': 4372293056,
'threadName': 'MainThread'}
5, đó là tệp bạn sẽ dành nhiều thời gian nhất ở đây:cpython/
│
├── Lib/
│ ├── logging/
│ │ ├── __init__.py
│ │ ├── config.py
│ │ └── handlers.py
│ ├── ...
├── Modules/
├── Include/
...
... [truncated]
Với điều đó, hãy để nhảy vào.
Sơ bộ
Trước khi chúng tôi đến các lớp học hạng nặng, hàng trăm dòng hàng đầu của
[Pdb] l
1514 exc_info = [type[exc_info], exc_info, exc_info.__traceback__]
1515 elif not isinstance[exc_info, tuple]:
1516 exc_info = sys.exc_info[]
1517 record = self.makeRecord[self.name, level, fn, lno, msg, args,
1518 exc_info, func, extra, sinfo]
1519 -> self.handle[record]
1520
1521 def handle[self, record]:
1522 """
1523 Call the handlers for the specified record.
1524
[Pdb] from pprint import pprint
[Pdb] pprint[vars[record]]
{'args': [],
'created': 1550671851.660067,
'exc_info': None,
'exc_text': None,
'filename': '',
'funcName': 'f',
'levelname': 'ERROR',
'levelno': 40,
'lineno': 2,
'module': '',
'msecs': 660.067081451416,
'msg': 'bad vibes',
'name': 'root',
'pathname': '',
'process': 2360,
'processName': 'MainProcess',
'relativeCreated': 295145.5490589142,
'stack_info': None,
'thread': 4372293056,
'threadName': 'MainThread'}
6 giới thiệu một vài khái niệm tinh tế nhưng quan trọng.Sơ bộ số 1: Một cấp độ chỉ là một [Pdb] l
1514 exc_info = [type[exc_info], exc_info, exc_info.__traceback__]
1515 elif not isinstance[exc_info, tuple]:
1516 exc_info = sys.exc_info[]
1517 record = self.makeRecord[self.name, level, fn, lno, msg, args,
1518 exc_info, func, extra, sinfo]
1519 -> self.handle[record]
1520
1521 def handle[self, record]:
1522 """
1523 Call the handlers for the specified record.
1524
[Pdb] from pprint import pprint
[Pdb] pprint[vars[record]]
{'args': [],
'created': 1550671851.660067,
'exc_info': None,
'exc_text': None,
'filename': '',
'funcName': 'f',
'levelname': 'ERROR',
'levelno': 40,
'lineno': 2,
'module': '',
'msecs': 660.067081451416,
'msg': 'bad vibes',
'name': 'root',
'pathname': '',
'process': 2360,
'processName': 'MainProcess',
'relativeCreated': 295145.5490589142,
'stack_info': None,
'thread': 4372293056,
'threadName': 'MainThread'}
7!
[Pdb] l
1514 exc_info = [type[exc_info], exc_info, exc_info.__traceback__]
1515 elif not isinstance[exc_info, tuple]:
1516 exc_info = sys.exc_info[]
1517 record = self.makeRecord[self.name, level, fn, lno, msg, args,
1518 exc_info, func, extra, sinfo]
1519 -> self.handle[record]
1520
1521 def handle[self, record]:
1522 """
1523 Call the handlers for the specified record.
1524
[Pdb] from pprint import pprint
[Pdb] pprint[vars[record]]
{'args': [],
'created': 1550671851.660067,
'exc_info': None,
'exc_text': None,
'filename': '',
'funcName': 'f',
'levelname': 'ERROR',
'levelno': 40,
'lineno': 2,
'module': '',
'msecs': 660.067081451416,
'msg': 'bad vibes',
'name': 'root',
'pathname': '',
'process': 2360,
'processName': 'MainProcess',
'relativeCreated': 295145.5490589142,
'stack_info': None,
'thread': 4372293056,
'threadName': 'MainThread'}
Các đối tượng như
[Pdb] l
1514 exc_info = [type[exc_info], exc_info, exc_info.__traceback__]
1515 elif not isinstance[exc_info, tuple]:
1516 exc_info = sys.exc_info[]
1517 record = self.makeRecord[self.name, level, fn, lno, msg, args,
1518 exc_info, func, extra, sinfo]
1519 -> self.handle[record]
1520
1521 def handle[self, record]:
1522 """
1523 Call the handlers for the specified record.
1524
[Pdb] from pprint import pprint
[Pdb] pprint[vars[record]]
{'args': [],
'created': 1550671851.660067,
'exc_info': None,
'exc_text': None,
'filename': '',
'funcName': 'f',
'levelname': 'ERROR',
'levelno': 40,
'lineno': 2,
'module': '',
'msecs': 660.067081451416,
'msg': 'bad vibes',
'name': 'root',
'pathname': '',
'process': 2360,
'processName': 'MainProcess',
'relativeCreated': 295145.5490589142,
'stack_info': None,
'thread': 4372293056,
'threadName': 'MainThread'}
8 hoặc [Pdb] l
1514 exc_info = [type[exc_info], exc_info, exc_info.__traceback__]
1515 elif not isinstance[exc_info, tuple]:
1516 exc_info = sys.exc_info[]
1517 record = self.makeRecord[self.name, level, fn, lno, msg, args,
1518 exc_info, func, extra, sinfo]
1519 -> self.handle[record]
1520
1521 def handle[self, record]:
1522 """
1523 Call the handlers for the specified record.
1524
[Pdb] from pprint import pprint
[Pdb] pprint[vars[record]]
{'args': [],
'created': 1550671851.660067,
'exc_info': None,
'exc_text': None,
'filename': '',
'funcName': 'f',
'levelname': 'ERROR',
'levelno': 40,
'lineno': 2,
'module': '',
'msecs': 660.067081451416,
'msg': 'bad vibes',
'name': 'root',
'pathname': '',
'process': 2360,
'processName': 'MainProcess',
'relativeCreated': 295145.5490589142,
'stack_info': None,
'thread': 4372293056,
'threadName': 'MainThread'}
9 có vẻ hơi mờ. Những biến này là gì trong nội bộ, và chúng được xác định như thế nào?Trên thực tế, các hằng số chữ hoa từ Python,
import logging
import sys
logger = logging.getLogger["pylog"]
logger.setLevel[logging.DEBUG]
h2 = logging.FileHandler[filename="/tmp/records.log"]
h2.setLevel[logging.INFO]
h2 = logging.StreamHandler[sys.stderr]
h2.setLevel[logging.ERROR]
logger.addHandler[h2]
logger.addHandler[h2]
logger.info["testing %d.. %d.. %d..", 1, 2, 3]
5 chỉ là các số nguyên, tạo thành một bộ sưu tập giống như enum của các cấp số:CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
Tại sao không chỉ sử dụng các chuỗi
class Logger[Filterer]:
# ...
def getEffectiveLevel[self]:
logger = self
while logger:
if logger.level:
return logger.level
logger = logger.parent
return NOTSET
def isEnabledFor[self, level]:
try:
return self._cache[level]
except KeyError:
_acquireLock[]
if self.manager.disable >= level:
is_enabled = self._cache[level] = False
else:
is_enabled = self._cache[level] = level >= self.getEffectiveLevel[]
_releaseLock[]
return is_enabled
1 hoặc class Logger[Filterer]:
# ...
def getEffectiveLevel[self]:
logger = self
while logger:
if logger.level:
return logger.level
logger = logger.parent
return NOTSET
def isEnabledFor[self, level]:
try:
return self._cache[level]
except KeyError:
_acquireLock[]
if self.manager.disable >= level:
is_enabled = self._cache[level] = False
else:
is_enabled = self._cache[level] = level >= self.getEffectiveLevel[]
_releaseLock[]
return is_enabled
2? Các cấp là hằng số ____777 để cho phép so sánh đơn giản, rõ ràng của một cấp với một cấp khác. Họ cũng được đặt tên để cho họ mượn ý nghĩa ngữ nghĩa. Nói rằng một tin nhắn có mức độ nghiêm trọng là 50 có thể không rõ ràng ngay lập tức, nhưng nói rằng nó có mức độ class Logger[Filterer]:
# ...
def getEffectiveLevel[self]:
logger = self
while logger:
if logger.level:
return logger.level
logger = logger.parent
return NOTSET
def isEnabledFor[self, level]:
try:
return self._cache[level]
except KeyError:
_acquireLock[]
if self.manager.disable >= level:
is_enabled = self._cache[level] = False
else:
is_enabled = self._cache[level] = level >= self.getEffectiveLevel[]
_releaseLock[]
return is_enabled
4 cho bạn biết rằng bạn đã có đèn đỏ nhấp nháy ở đâu đó trong chương trình của bạn.Bây giờ, về mặt kỹ thuật, bạn chỉ có thể vượt qua dạng
class Logger[Filterer]:
# ...
def getEffectiveLevel[self]:
logger = self
while logger:
if logger.level:
return logger.level
logger = logger.parent
return NOTSET
def isEnabledFor[self, level]:
try:
return self._cache[level]
except KeyError:
_acquireLock[]
if self.manager.disable >= level:
is_enabled = self._cache[level] = False
else:
is_enabled = self._cache[level] = level >= self.getEffectiveLevel[]
_releaseLock[]
return is_enabled
5 của một cấp độ ở một số nơi, chẳng hạn như class Logger[Filterer]:
# ...
def getEffectiveLevel[self]:
logger = self
while logger:
if logger.level:
return logger.level
logger = logger.parent
return NOTSET
def isEnabledFor[self, level]:
try:
return self._cache[level]
except KeyError:
_acquireLock[]
if self.manager.disable >= level:
is_enabled = self._cache[level] = False
else:
is_enabled = self._cache[level] = level >= self.getEffectiveLevel[]
_releaseLock[]
return is_enabled
6. Trong nội bộ, điều này sẽ gọi class Logger[Filterer]:
# ...
def getEffectiveLevel[self]:
logger = self
while logger:
if logger.level:
return logger.level
logger = logger.parent
return NOTSET
def isEnabledFor[self, level]:
try:
return self._cache[level]
except KeyError:
_acquireLock[]
if self.manager.disable >= level:
is_enabled = self._cache[level] = False
else:
is_enabled = self._cache[level] = level >= self.getEffectiveLevel[]
_releaseLock[]
return is_enabled
7, cuối cùng thực hiện tìm kiếm class Logger[Filterer]:
# ...
def getEffectiveLevel[self]:
logger = self
while logger:
if logger.level:
return logger.level
logger = logger.parent
return NOTSET
def isEnabledFor[self, level]:
try:
return self._cache[level]
except KeyError:
_acquireLock[]
if self.manager.disable >= level:
is_enabled = self._cache[level] = False
else:
is_enabled = self._cache[level] = level >= self.getEffectiveLevel[]
_releaseLock[]
return is_enabled
8 cho [Pdb] l
1514 exc_info = [type[exc_info], exc_info, exc_info.__traceback__]
1515 elif not isinstance[exc_info, tuple]:
1516 exc_info = sys.exc_info[]
1517 record = self.makeRecord[self.name, level, fn, lno, msg, args,
1518 exc_info, func, extra, sinfo]
1519 -> self.handle[record]
1520
1521 def handle[self, record]:
1522 """
1523 Call the handlers for the specified record.
1524
[Pdb] from pprint import pprint
[Pdb] pprint[vars[record]]
{'args': [],
'created': 1550671851.660067,
'exc_info': None,
'exc_text': None,
'filename': '',
'funcName': 'f',
'levelname': 'ERROR',
'levelno': 40,
'lineno': 2,
'module': '',
'msecs': 660.067081451416,
'msg': 'bad vibes',
'name': 'root',
'pathname': '',
'process': 2360,
'processName': 'MainProcess',
'relativeCreated': 295145.5490589142,
'stack_info': None,
'thread': 4372293056,
'threadName': 'MainThread'}
7: tương ứng:_nameToLevel = {
'CRITICAL': CRITICAL,
'FATAL': FATAL,
'ERROR': ERROR,
'WARN': WARNING,
'WARNING': WARNING,
'INFO': INFO,
'DEBUG': DEBUG,
'NOTSET': NOTSET,
}
def _checkLevel[level]:
if isinstance[level, int]:
rv = level
elif str[level] == level:
if level not in _nameToLevel:
raise ValueError["Unknown level: %r" % level]
rv = _nameToLevel[level]
else:
raise TypeError["Level not an integer or a valid string: %r" % level]
return rv
Bạn nên thích cái nào hơn? Tôi không quá quan tâm đến điều này, nhưng điều đáng chú ý là các tài liệu
import logging
import sys
logger = logging.getLogger["pylog"]
logger.setLevel[logging.DEBUG]
h2 = logging.FileHandler[filename="/tmp/records.log"]
h2.setLevel[logging.INFO]
h2 = logging.StreamHandler[sys.stderr]
h2.setLevel[logging.ERROR]
logger.addHandler[h2]
logger.addHandler[h2]
logger.info["testing %d.. %d.. %d..", 1, 2, 3]
5 luôn sử dụng biểu mẫu [Pdb] l
1514 exc_info = [type[exc_info], exc_info, exc_info.__traceback__]
1515 elif not isinstance[exc_info, tuple]:
1516 exc_info = sys.exc_info[]
1517 record = self.makeRecord[self.name, level, fn, lno, msg, args,
1518 exc_info, func, extra, sinfo]
1519 -> self.handle[record]
1520
1521 def handle[self, record]:
1522 """
1523 Call the handlers for the specified record.
1524
[Pdb] from pprint import pprint
[Pdb] pprint[vars[record]]
{'args': [],
'created': 1550671851.660067,
'exc_info': None,
'exc_text': None,
'filename': '',
'funcName': 'f',
'levelname': 'ERROR',
'levelno': 40,
'lineno': 2,
'module': '',
'msecs': 660.067081451416,
'msg': 'bad vibes',
'name': 'root',
'pathname': '',
'process': 2360,
'processName': 'MainProcess',
'relativeCreated': 295145.5490589142,
'stack_info': None,
'thread': 4372293056,
'threadName': 'MainThread'}
9 thay vì class Logger[Filterer]:
# ...
def getEffectiveLevel[self]:
logger = self
while logger:
if logger.level:
return logger.level
logger = logger.parent
return NOTSET
def isEnabledFor[self, level]:
try:
return self._cache[level]
except KeyError:
_acquireLock[]
if self.manager.disable >= level:
is_enabled = self._cache[level] = False
else:
is_enabled = self._cache[level] = level >= self.getEffectiveLevel[]
_releaseLock[]
return is_enabled
2 hoặc >>> import logging
>>> logger = logging.getLogger["app"]
>>> logger.level # No!
0
>>> logger.getEffectiveLevel[]
30
>>> logger.parent
>>> logger.parent.level
30
3. Ngoài ra, việc chuyển mẫu class Logger[Filterer]:
# ...
def getEffectiveLevel[self]:
logger = self
while logger:
if logger.level:
return logger.level
logger = logger.parent
return NOTSET
def isEnabledFor[self, level]:
try:
return self._cache[level]
except KeyError:
_acquireLock[]
if self.manager.disable >= level:
is_enabled = self._cache[level] = False
else:
is_enabled = self._cache[level] = level >= self.getEffectiveLevel[]
_releaseLock[]
return is_enabled
5 không phải là một tùy chọn trong Python 2 và một số phương pháp import logging
import sys
logger = logging.getLogger["pylog"]
logger.setLevel[logging.DEBUG]
h2 = logging.FileHandler[filename="/tmp/records.log"]
h2.setLevel[logging.INFO]
h2 = logging.StreamHandler[sys.stderr]
h2.setLevel[logging.ERROR]
logger.addHandler[h2]
logger.addHandler[h2]
logger.info["testing %d.. %d.. %d..", 1, 2, 3]
5 như >>> import logging
>>> logger = logging.getLogger["app"]
>>> logger.level # No!
0
>>> logger.getEffectiveLevel[]
30
>>> logger.parent
>>> logger.parent.level
30
6 sẽ chỉ chấp nhận một [Pdb] l
1514 exc_info = [type[exc_info], exc_info, exc_info.__traceback__]
1515 elif not isinstance[exc_info, tuple]:
1516 exc_info = sys.exc_info[]
1517 record = self.makeRecord[self.name, level, fn, lno, msg, args,
1518 exc_info, func, extra, sinfo]
1519 -> self.handle[record]
1520
1521 def handle[self, record]:
1522 """
1523 Call the handlers for the specified record.
1524
[Pdb] from pprint import pprint
[Pdb] pprint[vars[record]]
{'args': [],
'created': 1550671851.660067,
'exc_info': None,
'exc_text': None,
'filename': '',
'funcName': 'f',
'levelname': 'ERROR',
'levelno': 40,
'lineno': 2,
'module': '',
'msecs': 660.067081451416,
'msg': 'bad vibes',
'name': 'root',
'pathname': '',
'process': 2360,
'processName': 'MainProcess',
'relativeCreated': 295145.5490589142,
'stack_info': None,
'thread': 4372293056,
'threadName': 'MainThread'}
7, chứ không phải là anh em họ ____85 của nó.Sơ bộ #2: Ghi nhật ký là an toàn cho luồng, nhưng không an toàn quá trình
Một vài dòng xuống, bạn sẽ tìm thấy khối mã ngắn sau đây, điều này rất quan trọng đối với toàn bộ gói:
import threading
_lock = threading.RLock[]
def _acquireLock[]:
if _lock:
_lock.acquire[]
def _releaseLock[]:
if _lock:
_lock.release[]
Đối tượng
>>> import logging
>>> logger = logging.getLogger["app"]
>>> logger.level # No!
0
>>> logger.getEffectiveLevel[]
30
>>> logger.parent
>>> logger.parent.level
30
9 là một khóa reentrant nằm trong không gian tên toàn cầu của mô -đun [Pdb] l
1514 exc_info = [type[exc_info], exc_info, exc_info.__traceback__]
1515 elif not isinstance[exc_info, tuple]:
1516 exc_info = sys.exc_info[]
1517 record = self.makeRecord[self.name, level, fn, lno, msg, args,
1518 exc_info, func, extra, sinfo]
1519 -> self.handle[record]
1520
1521 def handle[self, record]:
1522 """
1523 Call the handlers for the specified record.
1524
[Pdb] from pprint import pprint
[Pdb] pprint[vars[record]]
{'args': [],
'created': 1550671851.660067,
'exc_info': None,
'exc_text': None,
'filename': '',
'funcName': 'f',
'levelname': 'ERROR',
'levelno': 40,
'lineno': 2,
'module': '',
'msecs': 660.067081451416,
'msg': 'bad vibes',
'name': 'root',
'pathname': '',
'process': 2360,
'processName': 'MainProcess',
'relativeCreated': 295145.5490589142,
'stack_info': None,
'thread': 4372293056,
'threadName': 'MainThread'}
5. Nó làm cho khá nhiều đối tượng và hoạt động trong toàn bộ gói an toàn cho luồng import logging
import sys
logger = logging.getLogger["pylog"]
logger.setLevel[logging.DEBUG]
h2 = logging.FileHandler[filename="/tmp/records.log"]
h2.setLevel[logging.INFO]
h2 = logging.StreamHandler[sys.stderr]
h2.setLevel[logging.ERROR]
logger.addHandler[h2]
logger.addHandler[h2]
logger.info["testing %d.. %d.. %d..", 1, 2, 3]
5, cho phép các luồng thực hiện các hoạt động đọc và viết mà không cần mối đe dọa của một điều kiện chủng tộc. Bạn có thể thấy trong mã nguồn mô -đun mà CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
02 và CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
03 có mặt khắp nơi đối với mô -đun và các lớp của nó.Mặc dù vậy, có một cái gì đó không được tính ở đây: còn an toàn quá trình thì sao? Câu trả lời ngắn gọn là mô -đun
import logging
import sys
logger = logging.getLogger["pylog"]
logger.setLevel[logging.DEBUG]
h2 = logging.FileHandler[filename="/tmp/records.log"]
h2.setLevel[logging.INFO]
h2 = logging.StreamHandler[sys.stderr]
h2.setLevel[logging.ERROR]
logger.addHandler[h2]
logger.addHandler[h2]
logger.info["testing %d.. %d.. %d..", 1, 2, 3]
5 không được xử lý an toàn. Đây không phải là lỗi của ____ 55, nói chung, hai quy trình có thể viết vào cùng một tệp mà không cần nhiều nỗ lực chủ động thay mặt cho lập trình viên trước.Điều này có nghĩa là bạn sẽ muốn cẩn thận trước khi sử dụng các lớp như
CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
06 có liên quan. Nếu hai quy trình muốn đọc và ghi vào cùng một tệp bên dưới, thì bạn có thể chạy vào một lỗi khó chịu giữa một thói quen chạy dài.Nếu bạn muốn vượt qua giới hạn này, thì có một công thức kỹ lưỡng trong cuốn sách nấu ăn chính thức. Bởi vì điều này đòi hỏi một lượng thiết lập kha khá, một cách khác là có mỗi nhật ký quy trình vào một tệp riêng dựa trên ID quy trình của nó, mà bạn có thể lấy với
CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
07.Kiến trúc gói: Ghi nhật ký MRO MRO
Bây giờ, chúng tôi đã đề cập đến một số mã thiết lập sơ bộ, hãy để có một cái nhìn cấp cao về cách
import logging
import sys
logger = logging.getLogger["pylog"]
logger.setLevel[logging.DEBUG]
h2 = logging.FileHandler[filename="/tmp/records.log"]
h2.setLevel[logging.INFO]
h2 = logging.StreamHandler[sys.stderr]
h2.setLevel[logging.ERROR]
logger.addHandler[h2]
logger.addHandler[h2]
logger.info["testing %d.. %d.. %d..", 1, 2, 3]
5 được đặt ra. Gói import logging
import sys
logger = logging.getLogger["pylog"]
logger.setLevel[logging.DEBUG]
h2 = logging.FileHandler[filename="/tmp/records.log"]
h2.setLevel[logging.INFO]
h2 = logging.StreamHandler[sys.stderr]
h2.setLevel[logging.ERROR]
logger.addHandler[h2]
logger.addHandler[h2]
logger.info["testing %d.. %d.. %d..", 1, 2, 3]
5 sử dụng một liều OOP và thừa kế lành mạnh. Ở đây, một cái nhìn một phần về thứ tự phân giải phương thức [MRO] cho một số lớp quan trọng nhất trong gói:object
│
├── LogRecord
├── Filterer
│ ├── Logger
│ │ └── RootLogger
│ └── Handler
│ ├── StreamHandler
│ └── NullHandler
├── Filter
└── Manager
Biểu đồ cây trên không bao gồm tất cả các lớp trong mô -đun, chỉ là những lớp đáng để làm nổi bật nhất.
Litany của các lớp học này thường là một nguồn gây nhầm lẫn bởi vì có rất nhiều điều đang diễn ra, và nó tất cả đều nặng về biệt ngữ.
CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
10 so với CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
11? CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
12 so với CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
13? Nó có thể là một thách thức để theo dõi mọi thứ, ít hình dung hơn về cách nó phù hợp với nhau. Một bức tranh có giá trị một nghìn từ, vì vậy, đây là một sơ đồ của một kịch bản trong đó một logger với hai trình xử lý được gắn vào nó viết một thông báo nhật ký với cấp độ [Pdb] l
1514 exc_info = [type[exc_info], exc_info, exc_info.__traceback__]
1515 elif not isinstance[exc_info, tuple]:
1516 exc_info = sys.exc_info[]
1517 record = self.makeRecord[self.name, level, fn, lno, msg, args,
1518 exc_info, func, extra, sinfo]
1519 -> self.handle[record]
1520
1521 def handle[self, record]:
1522 """
1523 Call the handlers for the specified record.
1524
[Pdb] from pprint import pprint
[Pdb] pprint[vars[record]]
{'args': [],
'created': 1550671851.660067,
'exc_info': None,
'exc_text': None,
'filename': '',
'funcName': 'f',
'levelname': 'ERROR',
'levelno': 40,
'lineno': 2,
'module': '',
'msecs': 660.067081451416,
'msg': 'bad vibes',
'name': 'root',
'pathname': '',
'process': 2360,
'processName': 'MainProcess',
'relativeCreated': 295145.5490589142,
'stack_info': None,
'thread': 4372293056,
'threadName': 'MainThread'}
8:Trong mã Python, mọi thứ trên sẽ trông như thế này:
import logging
import sys
logger = logging.getLogger["pylog"]
logger.setLevel[logging.DEBUG]
h2 = logging.FileHandler[filename="/tmp/records.log"]
h2.setLevel[logging.INFO]
h2 = logging.StreamHandler[sys.stderr]
h2.setLevel[logging.ERROR]
logger.addHandler[h2]
logger.addHandler[h2]
logger.info["testing %d.. %d.. %d..", 1, 2, 3]
Có một bản đồ chi tiết hơn về dòng chảy này trong việc ghi nhật ký. Những gì mà hiển thị ở trên là một kịch bản đơn giản hóa.
Mã của bạn chỉ xác định một ví dụ
CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
12, CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
16, cùng với hai trường hợp CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
13, CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
18 và CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
18.Khi bạn gọi
CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
20, đối tượng CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
16 đóng vai trò là bộ lọc vì nó cũng có CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
22 được liên kết với nó. Chỉ khi mức độ tin nhắn đủ nghiêm trọng, logger mới làm bất cứ điều gì với tin nhắn. Bởi vì logger có mức CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
23 và thông báo mang mức độ CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
24 cao hơn, nó sẽ tiếp tục đi trước.Trong nội bộ,
CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
16 gọi CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
26 để đặt chuỗi tin nhắn CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
27 và các đối số của nó CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
28 vào một phiên bản lớp bona fide của CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
29, chỉ là một thùng chứa cho tin nhắn và siêu dữ liệu của nó.Đối tượng
CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
16 tìm kiếm các trình xử lý của nó [các trường hợp CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
13], có thể được gắn trực tiếp với chính CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
16 hoặc với cha mẹ của nó [một khái niệm mà chúng tôi sẽ chạm vào sau]. Trong ví dụ này, nó tìm thấy hai trình xử lý:- Một với cấp độ
24 gửi dữ liệu nhật ký vào một tệp tạiCRITICAL = 50 FATAL = CRITICAL ERROR = 40 WARNING = 30 WARN = WARNING INFO = 20 DEBUG = 10 NOTSET = 0
34CRITICAL = 50 FATAL = CRITICAL ERROR = 40 WARNING = 30 WARN = WARNING INFO = 20 DEBUG = 10 NOTSET = 0
- Một bản ghi vào
35 nhưng chỉ khi tin nhắn đến ở cấp độCRITICAL = 50 FATAL = CRITICAL ERROR = 40 WARNING = 30 WARN = WARNING INFO = 20 DEBUG = 10 NOTSET = 0
36 trở lênCRITICAL = 50 FATAL = CRITICAL ERROR = 40 WARNING = 30 WARN = WARNING INFO = 20 DEBUG = 10 NOTSET = 0
Tại thời điểm này, có một vòng thử nghiệm khác. Đối với những người xử lý, viết
CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
29 vào luồng của họ được gọi là phát ra nó, được chụp trong CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
41 của họ.emitting it, which is captured in their
CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
41.Tiếp theo, hãy để LỚN mổ xẻ mọi thứ từ trên cao.
Lớp CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
29
CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
29 là gì? Khi bạn đăng nhập một tin nhắn, một thể hiện của lớp CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
29 là đối tượng bạn gửi để được ghi lại. Nó được tạo ra cho bạn bởi một ví dụ CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
12 và gói gọn tất cả các thông tin thích hợp về sự kiện đó. Trong nội bộ, nó rất ít hơn một trình bao bọc xung quanh class Logger[Filterer]:
# ...
def getEffectiveLevel[self]:
logger = self
while logger:
if logger.level:
return logger.level
logger = logger.parent
return NOTSET
def isEnabledFor[self, level]:
try:
return self._cache[level]
except KeyError:
_acquireLock[]
if self.manager.disable >= level:
is_enabled = self._cache[level] = False
else:
is_enabled = self._cache[level] = level >= self.getEffectiveLevel[]
_releaseLock[]
return is_enabled
8 chứa các thuộc tính cho hồ sơ. Một ví dụ CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
12 gửi một thể hiện CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
29 đến các phiên bản CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
13 hoặc nhiều hơn.CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
29 chứa một số siêu dữ liệu, chẳng hạn như sau:- Một cái tên
- Thời gian sáng tạo như một dấu thời gian unix
- Thông điệp chính nó
- Thông tin về chức năng nào đã thực hiện cuộc gọi ghi nhật ký
Ở đây, một cái nhìn vào siêu dữ liệu mà nó mang theo với nó, mà bạn có thể hướng nội bằng cách bước qua một cuộc gọi
CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
51 với mô -đun CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
52:>>>
>>> import logging
>>> import pdb
>>> def f[x]:
... logging.error["bad vibes"]
... return x / 0
...
>>> pdb.run["f[1]"]
Sau khi bước qua một số chức năng cấp cao hơn, bạn sẽ kết thúc ở dòng 1517:
[Pdb] l
1514 exc_info = [type[exc_info], exc_info, exc_info.__traceback__]
1515 elif not isinstance[exc_info, tuple]:
1516 exc_info = sys.exc_info[]
1517 record = self.makeRecord[self.name, level, fn, lno, msg, args,
1518 exc_info, func, extra, sinfo]
1519 -> self.handle[record]
1520
1521 def handle[self, record]:
1522 """
1523 Call the handlers for the specified record.
1524
[Pdb] from pprint import pprint
[Pdb] pprint[vars[record]]
{'args': [],
'created': 1550671851.660067,
'exc_info': None,
'exc_text': None,
'filename': '',
'funcName': 'f',
'levelname': 'ERROR',
'levelno': 40,
'lineno': 2,
'module': '',
'msecs': 660.067081451416,
'msg': 'bad vibes',
'name': 'root',
'pathname': '',
'process': 2360,
'processName': 'MainProcess',
'relativeCreated': 295145.5490589142,
'stack_info': None,
'thread': 4372293056,
'threadName': 'MainThread'}
Một
CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
29, trong nội bộ, chứa một kho siêu dữ liệu mà sử dụng theo cách này hay cách khác.Bạn hiếm khi cần phải đối phó trực tiếp với
CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
29, vì CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
12 và CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
13 làm điều này cho bạn. Nó vẫn còn đáng để biết thông tin nào được kết thúc trong một CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
29, bởi vì đây là nơi mà tất cả thông tin hữu ích đó, như dấu thời gian, đến từ khi bạn thấy các tin nhắn nhật ký ghi.Các lớp CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
12 và CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
13
CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
Các lớp
CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
12 và CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
13 đều là trung tâm của cách import logging
import sys
logger = logging.getLogger["pylog"]
logger.setLevel[logging.DEBUG]
h2 = logging.FileHandler[filename="/tmp/records.log"]
h2.setLevel[logging.INFO]
h2 = logging.StreamHandler[sys.stderr]
h2.setLevel[logging.ERROR]
logger.addHandler[h2]
logger.addHandler[h2]
logger.info["testing %d.. %d.. %d..", 1, 2, 3]
5 hoạt động và chúng tương tác với nhau thường xuyên. A CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
12, A CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
13 và A CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
29 mỗi CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
66 liên quan đến chúng.
CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
12 lấy CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
29 và chuyển nó đến CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
13, nhưng chỉ khi mức hiệu quả của CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
29 bằng hoặc cao hơn so với CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
12. Điều tương tự cũng xảy ra với bài kiểm tra CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
29 so với CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
13. Điều này được gọi là lọc dựa trên cấp độ, trong đó CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
12 và CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
13 thực hiện theo những cách hơi khác nhau.level-based filtering, which CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
12 and CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
13 implement in slightly different ways.Nói cách khác, có một bài kiểm tra hai bước [ít nhất] được áp dụng trước khi thông báo mà bạn đăng nhập sẽ đi bất cứ đâu. Để được truyền hoàn toàn từ bộ ghi sang xử lý và sau đó đăng nhập vào luồng cuối [có thể là
CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
76, một tệp hoặc email qua SMTP], CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
29 phải có mức cao nhất là cả bộ ghi và trình xử lý .PEP 282 mô tả cách thức hoạt động của nó:
Mỗi đối tượng
12 theo dõi mức nhật ký [hoặc ngưỡng] mà nó quan tâm và loại bỏ các yêu cầu nhật ký dưới mức đó. [Nguồn]CRITICAL = 50 FATAL = CRITICAL ERROR = 40 WARNING = 30 WARN = WARNING INFO = 20 DEBUG = 10 NOTSET = 0
Vậy bộ lọc dựa trên cấp độ này thực sự xảy ra ở đâu cho cả
CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
12 và CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
13?Đối với lớp
CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
12, nó là một giả định đầu tiên hợp lý rằng logger sẽ so sánh thuộc tính CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
66 của nó với cấp độ của CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
29 và được thực hiện ở đó. Tuy nhiên, nó có liên quan nhiều hơn thế.Lọc dựa trên cấp độ cho logger xảy ra trong
CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
84, từ đó gọi CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
85. Luôn luôn sử dụng CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
86 thay vì chỉ tư vấn CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
87. Lý do liên quan đến việc tổ chức các đối tượng CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
12 trong một không gian tên phân cấp. [Bạn sẽ thấy nhiều hơn về điều này sau.]Theo mặc định, một thể hiện
CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
12 có mức CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
90 [CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
91]. Tuy nhiên, loggers cũng có bộ ghi nhật ký cha mẹ, một trong số đó là logger gốc, có chức năng là cha mẹ của tất cả các trình ghi nhật ký khác. Một CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
12 sẽ đi lên trên phân cấp của nó và có được mức độ hiệu quả của nó là cha mẹ của nó [cuối cùng có thể là CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
93 nếu không có cha mẹ nào được tìm thấy].parent loggers, one of which is the root logger, which functions as the parent of all other loggers. A CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
12 will walk upwards in its hierarchy and get its effective level vis-à-vis its parent [which ultimately may be CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
93 if no other parents are found].Ở đây, nơi mà điều này xảy ra trong lớp
CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
12:class Logger[Filterer]:
# ...
def getEffectiveLevel[self]:
logger = self
while logger:
if logger.level:
return logger.level
logger = logger.parent
return NOTSET
def isEnabledFor[self, level]:
try:
return self._cache[level]
except KeyError:
_acquireLock[]
if self.manager.disable >= level:
is_enabled = self._cache[level] = False
else:
is_enabled = self._cache[level] = level >= self.getEffectiveLevel[]
_releaseLock[]
return is_enabled
Tương ứng, ở đây, một ví dụ gọi mã nguồn mà bạn thấy ở trên:
>>>
>>> import logging
>>> logger = logging.getLogger["app"]
>>> logger.level # No!
0
>>> logger.getEffectiveLevel[]
30
>>> logger.parent
>>> logger.parent.level
30
Ở đây, người ta đang bỏ đi: Don lồng dựa vào
CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
66. Nếu bạn không đặt một cấp độ trên đối tượng CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
16 của bạn và bạn sẽ phụ thuộc vào CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
66 vì một số lý do, thì thiết lập đăng nhập của bạn có thể sẽ hoạt động khác với bạn mong đợi.Còn
CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
13 thì sao? Đối với người xử lý, so sánh cấp đến cấp độ đơn giản hơn, mặc dù nó thực sự xảy ra trong CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
99 từ lớp CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
12:CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
0Đối với một ví dụ
CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
29 đã cho [được đặt tên _nameToLevel = {
'CRITICAL': CRITICAL,
'FATAL': FATAL,
'ERROR': ERROR,
'WARN': WARNING,
'WARNING': WARNING,
'INFO': INFO,
'DEBUG': DEBUG,
'NOTSET': NOTSET,
}
def _checkLevel[level]:
if isinstance[level, int]:
rv = level
elif str[level] == level:
if level not in _nameToLevel:
raise ValueError["Unknown level: %r" % level]
rv = _nameToLevel[level]
else:
raise TypeError["Level not an integer or a valid string: %r" % level]
return rv
02 trong mã nguồn ở trên], một logger kiểm tra với từng trình xử lý đã đăng ký và kiểm tra nhanh trên thuộc tính CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
66 của phiên bản CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
13 đó. Nếu _nameToLevel = {
'CRITICAL': CRITICAL,
'FATAL': FATAL,
'ERROR': ERROR,
'WARN': WARNING,
'WARNING': WARNING,
'INFO': INFO,
'DEBUG': DEBUG,
'NOTSET': NOTSET,
}
def _checkLevel[level]:
if isinstance[level, int]:
rv = level
elif str[level] == level:
if level not in _nameToLevel:
raise ValueError["Unknown level: %r" % level]
rv = _nameToLevel[level]
else:
raise TypeError["Level not an integer or a valid string: %r" % level]
return rv
05 của CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
29 lớn hơn hoặc bằng với trình xử lý, chỉ sau đó, bản ghi được truyền lại. Một tài liệu trong import logging
import sys
logger = logging.getLogger["pylog"]
logger.setLevel[logging.DEBUG]
h2 = logging.FileHandler[filename="/tmp/records.log"]
h2.setLevel[logging.INFO]
h2 = logging.StreamHandler[sys.stderr]
h2.setLevel[logging.ERROR]
logger.addHandler[h2]
logger.addHandler[h2]
logger.info["testing %d.. %d.. %d..", 1, 2, 3]
5 đề cập đến điều này khi có điều kiện phát ra [ting] bản ghi ghi nhật ký được chỉ định.
Thuộc tính quan trọng nhất cho một thể hiện lớp con
CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
13 là thuộc tính _nameToLevel = {
'CRITICAL': CRITICAL,
'FATAL': FATAL,
'ERROR': ERROR,
'WARN': WARNING,
'WARNING': WARNING,
'INFO': INFO,
'DEBUG': DEBUG,
'NOTSET': NOTSET,
}
def _checkLevel[level]:
if isinstance[level, int]:
rv = level
elif str[level] == level:
if level not in _nameToLevel:
raise ValueError["Unknown level: %r" % level]
rv = _nameToLevel[level]
else:
raise TypeError["Level not an integer or a valid string: %r" % level]
return rv
09 của nó. Đây là đích đến cuối cùng mà nhật ký được ghi đến và có thể là khá nhiều đối tượng giống như tệp. Ở đây, một ví dụ với _nameToLevel = {
'CRITICAL': CRITICAL,
'FATAL': FATAL,
'ERROR': ERROR,
'WARN': WARNING,
'WARNING': WARNING,
'INFO': INFO,
'DEBUG': DEBUG,
'NOTSET': NOTSET,
}
def _checkLevel[level]:
if isinstance[level, int]:
rv = level
elif str[level] == level:
if level not in _nameToLevel:
raise ValueError["Unknown level: %r" % level]
rv = _nameToLevel[level]
else:
raise TypeError["Level not an integer or a valid string: %r" % level]
return rv
10, là một luồng trong bộ nhớ [bộ đệm] cho văn bản I/O.Đầu tiên, thiết lập một ví dụ
CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
12 với mức CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
23. Bạn sẽ thấy rằng, theo mặc định, nó không có trình xử lý trực tiếp:>>>
CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
1Tiếp theo, bạn có thể phân lớp
_nameToLevel = {
'CRITICAL': CRITICAL,
'FATAL': FATAL,
'ERROR': ERROR,
'WARN': WARNING,
'WARNING': WARNING,
'INFO': INFO,
'DEBUG': DEBUG,
'NOTSET': NOTSET,
}
def _checkLevel[level]:
if isinstance[level, int]:
rv = level
elif str[level] == level:
if level not in _nameToLevel:
raise ValueError["Unknown level: %r" % level]
rv = _nameToLevel[level]
else:
raise TypeError["Level not an integer or a valid string: %r" % level]
return rv
13 để làm cho _nameToLevel = {
'CRITICAL': CRITICAL,
'FATAL': FATAL,
'ERROR': ERROR,
'WARN': WARNING,
'WARNING': WARNING,
'INFO': INFO,
'DEBUG': DEBUG,
'NOTSET': NOTSET,
}
def _checkLevel[level]:
if isinstance[level, int]:
rv = level
elif str[level] == level:
if level not in _nameToLevel:
raise ValueError["Unknown level: %r" % level]
rv = _nameToLevel[level]
else:
raise TypeError["Level not an integer or a valid string: %r" % level]
return rv
14 gọi là không có. Chúng tôi muốn xả CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
35 hoặc CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
76, nhưng không phải là bộ đệm trong bộ nhớ trong trường hợp này:CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
2Bây giờ, hãy khai báo chính đối tượng bộ đệm và buộc nó là
_nameToLevel = {
'CRITICAL': CRITICAL,
'FATAL': FATAL,
'ERROR': ERROR,
'WARN': WARNING,
'WARNING': WARNING,
'INFO': INFO,
'DEBUG': DEBUG,
'NOTSET': NOTSET,
}
def _checkLevel[level]:
if isinstance[level, int]:
rv = level
elif str[level] == level:
if level not in _nameToLevel:
raise ValueError["Unknown level: %r" % level]
rv = _nameToLevel[level]
else:
raise TypeError["Level not an integer or a valid string: %r" % level]
return rv
09 cho trình xử lý tùy chỉnh của bạn với mức độ CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
24, sau đó buộc trình xử lý đó vào logger:>>>
CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
3Tiếp theo, bạn có thể phân lớp
_nameToLevel = {
'CRITICAL': CRITICAL,
'FATAL': FATAL,
'ERROR': ERROR,
'WARN': WARNING,
'WARNING': WARNING,
'INFO': INFO,
'DEBUG': DEBUG,
'NOTSET': NOTSET,
}
def _checkLevel[level]:
if isinstance[level, int]:
rv = level
elif str[level] == level:
if level not in _nameToLevel:
raise ValueError["Unknown level: %r" % level]
rv = _nameToLevel[level]
else:
raise TypeError["Level not an integer or a valid string: %r" % level]
return rv
13 để làm cho _nameToLevel = {
'CRITICAL': CRITICAL,
'FATAL': FATAL,
'ERROR': ERROR,
'WARN': WARNING,
'WARNING': WARNING,
'INFO': INFO,
'DEBUG': DEBUG,
'NOTSET': NOTSET,
}
def _checkLevel[level]:
if isinstance[level, int]:
rv = level
elif str[level] == level:
if level not in _nameToLevel:
raise ValueError["Unknown level: %r" % level]
rv = _nameToLevel[level]
else:
raise TypeError["Level not an integer or a valid string: %r" % level]
return rv
14 gọi là không có. Chúng tôi muốn xả CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
35 hoặc CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
76, nhưng không phải là bộ đệm trong bộ nhớ trong trường hợp này:Bây giờ, hãy khai báo chính đối tượng bộ đệm và buộc nó là
_nameToLevel = {
'CRITICAL': CRITICAL,
'FATAL': FATAL,
'ERROR': ERROR,
'WARN': WARNING,
'WARNING': WARNING,
'INFO': INFO,
'DEBUG': DEBUG,
'NOTSET': NOTSET,
}
def _checkLevel[level]:
if isinstance[level, int]:
rv = level
elif str[level] == level:
if level not in _nameToLevel:
raise ValueError["Unknown level: %r" % level]
rv = _nameToLevel[level]
else:
raise TypeError["Level not an integer or a valid string: %r" % level]
return rv
09 cho trình xử lý tùy chỉnh của bạn với mức độ CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
24, sau đó buộc trình xử lý đó vào logger:Chunk cuối cùng này là một minh họa khác về lọc dựa trên cấp độ.
Ba tin nhắn có cấp độ CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
23, _nameToLevel = {
'CRITICAL': CRITICAL,
'FATAL': FATAL,
'ERROR': ERROR,
'WARN': WARNING,
'WARNING': WARNING,
'INFO': INFO,
'DEBUG': DEBUG,
'NOTSET': NOTSET,
}
def _checkLevel[level]:
if isinstance[level, int]:
rv = level
elif str[level] == level:
if level not in _nameToLevel:
raise ValueError["Unknown level: %r" % level]
rv = _nameToLevel[level]
else:
raise TypeError["Level not an integer or a valid string: %r" % level]
return rv
20 và class Logger[Filterer]:
# ...
def getEffectiveLevel[self]:
logger = self
while logger:
if logger.level:
return logger.level
logger = logger.parent
return NOTSET
def isEnabledFor[self, level]:
try:
return self._cache[level]
except KeyError:
_acquireLock[]
if self.manager.disable >= level:
is_enabled = self._cache[level] = False
else:
is_enabled = self._cache[level] = level >= self.getEffectiveLevel[]
_releaseLock[]
return is_enabled
4 được truyền qua chuỗi. Lúc đầu, có vẻ như họ không đi đâu cả, nhưng hai người trong số họ làm. Tất cả ba người họ làm cho nó ra khỏi cổng từ CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
16 [có cấp độ CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
23].
CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
_nameToLevel = {
'CRITICAL': CRITICAL,
'FATAL': FATAL,
'ERROR': ERROR,
'WARN': WARNING,
'WARNING': WARNING,
'INFO': INFO,
'DEBUG': DEBUG,
'NOTSET': NOTSET,
}
def _checkLevel[level]:
if isinstance[level, int]:
rv = level
elif str[level] == level:
if level not in _nameToLevel:
raise ValueError["Unknown level: %r" % level]
rv = _nameToLevel[level]
else:
raise TypeError["Level not an integer or a valid string: %r" % level]
return rv
class Logger[Filterer]:
# ...
def getEffectiveLevel[self]:
logger = self
while logger:
if logger.level:
return logger.level
logger = logger.parent
return NOTSET
def isEnabledFor[self, level]:
try:
return self._cache[level]
except KeyError:
_acquireLock[]
if self.manager.disable >= level:
is_enabled = self._cache[level] = False
else:
is_enabled = self._cache[level] = level >= self.getEffectiveLevel[]
_releaseLock[]
return is_enabled
CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
Tuy nhiên, chỉ có hai trong số chúng được phát ra bởi người xử lý vì nó có mức độ
CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
24 cao hơn, vượt quá CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
23. Cuối cùng, bạn nhận được toàn bộ nội dung của bộ đệm dưới dạng class Logger[Filterer]:
# ...
def getEffectiveLevel[self]:
logger = self
while logger:
if logger.level:
return logger.level
logger = logger.parent
return NOTSET
def isEnabledFor[self, level]:
try:
return self._cache[level]
except KeyError:
_acquireLock[]
if self.manager.disable >= level:
is_enabled = self._cache[level] = False
else:
is_enabled = self._cache[level] = level >= self.getEffectiveLevel[]
_releaseLock[]
return is_enabled
5 và đóng bộ đệm để giải phóng các tài nguyên hệ thống một cách rõ ràng.Các lớp
CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
10 và CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
11Ở trên, chúng tôi đã hỏi câu hỏi, về việc lọc dựa trên cấp độ xảy ra ở đâu? Khi trả lời câu hỏi này, nó rất dễ bị phân tâm bởi các lớp
CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
10 và CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
11. Nghịch lý thay, lọc dựa trên cấp độ cho các trường hợp CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
12 và CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
13 xảy ra mà không có sự trợ giúp của các lớp CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
10 hoặc CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
11.CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
4CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
10 và CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
11 được thiết kế để cho phép bạn thêm các bộ lọc dựa trên chức năng bổ sung vào đầu bộ lọc dựa trên cấp độ được thực hiện theo mặc định. Tôi thích nghĩ về nó như là bộ lọc à la carte.CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
11 là lớp cơ sở cho CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
12 và CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
13 vì cả hai lớp này đều đủ điều kiện nhận các bộ lọc tùy chỉnh bổ sung mà bạn chỉ định. Bạn thêm các phiên bản CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
10 vào chúng với _nameToLevel = {
'CRITICAL': CRITICAL,
'FATAL': FATAL,
'ERROR': ERROR,
'WARN': WARNING,
'WARNING': WARNING,
'INFO': INFO,
'DEBUG': DEBUG,
'NOTSET': NOTSET,
}
def _checkLevel[level]:
if isinstance[level, int]:
rv = level
elif str[level] == level:
if level not in _nameToLevel:
raise ValueError["Unknown level: %r" % level]
rv = _nameToLevel[level]
else:
raise TypeError["Level not an integer or a valid string: %r" % level]
return rv
41 hoặc _nameToLevel = {
'CRITICAL': CRITICAL,
'FATAL': FATAL,
'ERROR': ERROR,
'WARN': WARNING,
'WARNING': WARNING,
'INFO': INFO,
'DEBUG': DEBUG,
'NOTSET': NOTSET,
}
def _checkLevel[level]:
if isinstance[level, int]:
rv = level
elif str[level] == level:
if level not in _nameToLevel:
raise ValueError["Unknown level: %r" % level]
rv = _nameToLevel[level]
else:
raise TypeError["Level not an integer or a valid string: %r" % level]
return rv
42, đó là những gì _nameToLevel = {
'CRITICAL': CRITICAL,
'FATAL': FATAL,
'ERROR': ERROR,
'WARN': WARNING,
'WARNING': WARNING,
'INFO': INFO,
'DEBUG': DEBUG,
'NOTSET': NOTSET,
}
def _checkLevel[level]:
if isinstance[level, int]:
rv = level
elif str[level] == level:
if level not in _nameToLevel:
raise ValueError["Unknown level: %r" % level]
rv = _nameToLevel[level]
else:
raise TypeError["Level not an integer or a valid string: %r" % level]
return rv
43 đề cập đến trong phương pháp sau:CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
5Đưa ra một
_nameToLevel = {
'CRITICAL': CRITICAL,
'FATAL': FATAL,
'ERROR': ERROR,
'WARN': WARNING,
'WARNING': WARNING,
'INFO': INFO,
'DEBUG': DEBUG,
'NOTSET': NOTSET,
}
def _checkLevel[level]:
if isinstance[level, int]:
rv = level
elif str[level] == level:
if level not in _nameToLevel:
raise ValueError["Unknown level: %r" % level]
rv = _nameToLevel[level]
else:
raise TypeError["Level not an integer or a valid string: %r" % level]
return rv
02 [là một ví dụ CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
29], _nameToLevel = {
'CRITICAL': CRITICAL,
'FATAL': FATAL,
'ERROR': ERROR,
'WARN': WARNING,
'WARNING': WARNING,
'INFO': INFO,
'DEBUG': DEBUG,
'NOTSET': NOTSET,
}
def _checkLevel[level]:
if isinstance[level, int]:
rv = level
elif str[level] == level:
if level not in _nameToLevel:
raise ValueError["Unknown level: %r" % level]
rv = _nameToLevel[level]
else:
raise TypeError["Level not an integer or a valid string: %r" % level]
return rv
46 trả về _nameToLevel = {
'CRITICAL': CRITICAL,
'FATAL': FATAL,
'ERROR': ERROR,
'WARN': WARNING,
'WARNING': WARNING,
'INFO': INFO,
'DEBUG': DEBUG,
'NOTSET': NOTSET,
}
def _checkLevel[level]:
if isinstance[level, int]:
rv = level
elif str[level] == level:
if level not in _nameToLevel:
raise ValueError["Unknown level: %r" % level]
rv = _nameToLevel[level]
else:
raise TypeError["Level not an integer or a valid string: %r" % level]
return rv
47 hoặc _nameToLevel = {
'CRITICAL': CRITICAL,
'FATAL': FATAL,
'ERROR': ERROR,
'WARN': WARNING,
'WARNING': WARNING,
'INFO': INFO,
'DEBUG': DEBUG,
'NOTSET': NOTSET,
}
def _checkLevel[level]:
if isinstance[level, int]:
rv = level
elif str[level] == level:
if level not in _nameToLevel:
raise ValueError["Unknown level: %r" % level]
rv = _nameToLevel[level]
else:
raise TypeError["Level not an integer or a valid string: %r" % level]
return rv
48 tùy thuộc vào việc bản ghi đó có ổn từ các bộ lọc lớp này hay không.>>>
CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
6Tiếp theo, bạn có thể phân lớp
_nameToLevel = {
'CRITICAL': CRITICAL,
'FATAL': FATAL,
'ERROR': ERROR,
'WARN': WARNING,
'WARNING': WARNING,
'INFO': INFO,
'DEBUG': DEBUG,
'NOTSET': NOTSET,
}
def _checkLevel[level]:
if isinstance[level, int]:
rv = level
elif str[level] == level:
if level not in _nameToLevel:
raise ValueError["Unknown level: %r" % level]
rv = _nameToLevel[level]
else:
raise TypeError["Level not an integer or a valid string: %r" % level]
return rv
13 để làm cho _nameToLevel = {
'CRITICAL': CRITICAL,
'FATAL': FATAL,
'ERROR': ERROR,
'WARN': WARNING,
'WARNING': WARNING,
'INFO': INFO,
'DEBUG': DEBUG,
'NOTSET': NOTSET,
}
def _checkLevel[level]:
if isinstance[level, int]:
rv = level
elif str[level] == level:
if level not in _nameToLevel:
raise ValueError["Unknown level: %r" % level]
rv = _nameToLevel[level]
else:
raise TypeError["Level not an integer or a valid string: %r" % level]
return rv
14 gọi là không có. Chúng tôi muốn xả CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
35 hoặc CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
76, nhưng không phải là bộ đệm trong bộ nhớ trong trường hợp này:Bây giờ, hãy khai báo chính đối tượng bộ đệm và buộc nó là _nameToLevel = {
'CRITICAL': CRITICAL,
'FATAL': FATAL,
'ERROR': ERROR,
'WARN': WARNING,
'WARNING': WARNING,
'INFO': INFO,
'DEBUG': DEBUG,
'NOTSET': NOTSET,
}
def _checkLevel[level]:
if isinstance[level, int]:
rv = level
elif str[level] == level:
if level not in _nameToLevel:
raise ValueError["Unknown level: %r" % level]
rv = _nameToLevel[level]
else:
raise TypeError["Level not an integer or a valid string: %r" % level]
return rv
09 cho trình xử lý tùy chỉnh của bạn với mức độ CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
24, sau đó buộc trình xử lý đó vào logger:
_nameToLevel = {
'CRITICAL': CRITICAL,
'FATAL': FATAL,
'ERROR': ERROR,
'WARN': WARNING,
'WARNING': WARNING,
'INFO': INFO,
'DEBUG': DEBUG,
'NOTSET': NOTSET,
}
def _checkLevel[level]:
if isinstance[level, int]:
rv = level
elif str[level] == level:
if level not in _nameToLevel:
raise ValueError["Unknown level: %r" % level]
rv = _nameToLevel[level]
else:
raise TypeError["Level not an integer or a valid string: %r" % level]
return rv
CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
Chunk cuối cùng này là một minh họa khác về lọc dựa trên cấp độ.
Ba tin nhắn có cấp độ CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
23, _nameToLevel = {
'CRITICAL': CRITICAL,
'FATAL': FATAL,
'ERROR': ERROR,
'WARN': WARNING,
'WARNING': WARNING,
'INFO': INFO,
'DEBUG': DEBUG,
'NOTSET': NOTSET,
}
def _checkLevel[level]:
if isinstance[level, int]:
rv = level
elif str[level] == level:
if level not in _nameToLevel:
raise ValueError["Unknown level: %r" % level]
rv = _nameToLevel[level]
else:
raise TypeError["Level not an integer or a valid string: %r" % level]
return rv
20 và class Logger[Filterer]:
# ...
def getEffectiveLevel[self]:
logger = self
while logger:
if logger.level:
return logger.level
logger = logger.parent
return NOTSET
def isEnabledFor[self, level]:
try:
return self._cache[level]
except KeyError:
_acquireLock[]
if self.manager.disable >= level:
is_enabled = self._cache[level] = False
else:
is_enabled = self._cache[level] = level >= self.getEffectiveLevel[]
_releaseLock[]
return is_enabled
4 được truyền qua chuỗi. Lúc đầu, có vẻ như họ không đi đâu cả, nhưng hai người trong số họ làm. Tất cả ba người họ làm cho nó ra khỏi cổng từ CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
16 [có cấp độ CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
23].
CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
_nameToLevel = {
'CRITICAL': CRITICAL,
'FATAL': FATAL,
'ERROR': ERROR,
'WARN': WARNING,
'WARNING': WARNING,
'INFO': INFO,
'DEBUG': DEBUG,
'NOTSET': NOTSET,
}
def _checkLevel[level]:
if isinstance[level, int]:
rv = level
elif str[level] == level:
if level not in _nameToLevel:
raise ValueError["Unknown level: %r" % level]
rv = _nameToLevel[level]
else:
raise TypeError["Level not an integer or a valid string: %r" % level]
return rv
class Logger[Filterer]:
# ...
def getEffectiveLevel[self]:
logger = self
while logger:
if logger.level:
return logger.level
logger = logger.parent
return NOTSET
def isEnabledFor[self, level]:
try:
return self._cache[level]
except KeyError:
_acquireLock[]
if self.manager.disable >= level:
is_enabled = self._cache[level] = False
else:
is_enabled = self._cache[level] = level >= self.getEffectiveLevel[]
_releaseLock[]
return is_enabled
CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
Tuy nhiên, chỉ có hai trong số chúng được phát ra bởi người xử lý vì nó có mức độ
CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
24 cao hơn, vượt quá CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
23. Cuối cùng, bạn nhận được toàn bộ nội dung của bộ đệm dưới dạng class Logger[Filterer]:
# ...
def getEffectiveLevel[self]:
logger = self
while logger:
if logger.level:
return logger.level
logger = logger.parent
return NOTSET
def isEnabledFor[self, level]:
try:
return self._cache[level]
except KeyError:
_acquireLock[]
if self.manager.disable >= level:
is_enabled = self._cache[level] = False
else:
is_enabled = self._cache[level] = level >= self.getEffectiveLevel[]
_releaseLock[]
return is_enabled
5 và đóng bộ đệm để giải phóng các tài nguyên hệ thống một cách rõ ràng.CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
7Các lớp
CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
10 và CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
11Ở trên, chúng tôi đã hỏi câu hỏi, về việc lọc dựa trên cấp độ xảy ra ở đâu? Khi trả lời câu hỏi này, nó rất dễ bị phân tâm bởi các lớp
10 vàCRITICAL = 50 FATAL = CRITICAL ERROR = 40 WARNING = 30 WARN = WARNING INFO = 20 DEBUG = 10 NOTSET = 0
11. Nghịch lý thay, lọc dựa trên cấp độ cho các trường hợpCRITICAL = 50 FATAL = CRITICAL ERROR = 40 WARNING = 30 WARN = WARNING INFO = 20 DEBUG = 10 NOTSET = 0
12 vàCRITICAL = 50 FATAL = CRITICAL ERROR = 40 WARNING = 30 WARN = WARNING INFO = 20 DEBUG = 10 NOTSET = 0
13 xảy ra mà không có sự trợ giúp của các lớpCRITICAL = 50 FATAL = CRITICAL ERROR = 40 WARNING = 30 WARN = WARNING INFO = 20 DEBUG = 10 NOTSET = 0
10 hoặcCRITICAL = 50 FATAL = CRITICAL ERROR = 40 WARNING = 30 WARN = WARNING INFO = 20 DEBUG = 10 NOTSET = 0
11.CRITICAL = 50 FATAL = CRITICAL ERROR = 40 WARNING = 30 WARN = WARNING INFO = 20 DEBUG = 10 NOTSET = 0
Lần lượt đối tượng
93 trở thành thuộc tính lớp cho lớpCRITICAL = 50 FATAL = CRITICAL ERROR = 40 WARNING = 30 WARN = WARNING INFO = 20 DEBUG = 10 NOTSET = 0
12. Điều này có nghĩa là tất cả các trường hợp củaCRITICAL = 50 FATAL = CRITICAL ERROR = 40 WARNING = 30 WARN = WARNING INFO = 20 DEBUG = 10 NOTSET = 0
12 và bản thân lớpCRITICAL = 50 FATAL = CRITICAL ERROR = 40 WARNING = 30 WARN = WARNING INFO = 20 DEBUG = 10 NOTSET = 0
12, tất cả đều có thuộc tínhCRITICAL = 50 FATAL = CRITICAL ERROR = 40 WARNING = 30 WARN = WARNING INFO = 20 DEBUG = 10 NOTSET = 0
73 là logger gốc. Đây là một ví dụ khác về mô hình giống như singleton đang được thi hành trong gói_nameToLevel = { 'CRITICAL': CRITICAL, 'FATAL': FATAL, 'ERROR': ERROR, 'WARN': WARNING, 'WARNING': WARNING, 'INFO': INFO, 'DEBUG': DEBUG, 'NOTSET': NOTSET, } def _checkLevel[level]: if isinstance[level, int]: rv = level elif str[level] == level: if level not in _nameToLevel: raise ValueError["Unknown level: %r" % level] rv = _nameToLevel[level] else: raise TypeError["Level not an integer or a valid string: %r" % level] return rv
5.class attribute for theimport logging import sys logger = logging.getLogger["pylog"] logger.setLevel[logging.DEBUG] h2 = logging.FileHandler[filename="/tmp/records.log"] h2.setLevel[logging.INFO] h2 = logging.StreamHandler[sys.stderr] h2.setLevel[logging.ERROR] logger.addHandler[h2] logger.addHandler[h2] logger.info["testing %d.. %d.. %d..", 1, 2, 3]
12 class. This means that all instances ofCRITICAL = 50 FATAL = CRITICAL ERROR = 40 WARNING = 30 WARN = WARNING INFO = 20 DEBUG = 10 NOTSET = 0
12, and theCRITICAL = 50 FATAL = CRITICAL ERROR = 40 WARNING = 30 WARN = WARNING INFO = 20 DEBUG = 10 NOTSET = 0
12 class itself, all have aCRITICAL = 50 FATAL = CRITICAL ERROR = 40 WARNING = 30 WARN = WARNING INFO = 20 DEBUG = 10 NOTSET = 0
73 attribute that is the root logger. This is another example of a singleton-like pattern being enforced in the_nameToLevel = { 'CRITICAL': CRITICAL, 'FATAL': FATAL, 'ERROR': ERROR, 'WARN': WARNING, 'WARNING': WARNING, 'INFO': INFO, 'DEBUG': DEBUG, 'NOTSET': NOTSET, } def _checkLevel[level]: if isinstance[level, int]: rv = level elif str[level] == level: if level not in _nameToLevel: raise ValueError["Unknown level: %r" % level] rv = _nameToLevel[level] else: raise TypeError["Level not an integer or a valid string: %r" % level] return rv
5 package.import logging import sys logger = logging.getLogger["pylog"] logger.setLevel[logging.DEBUG] h2 = logging.FileHandler[filename="/tmp/records.log"] h2.setLevel[logging.INFO] h2 = logging.StreamHandler[sys.stderr] h2.setLevel[logging.ERROR] logger.addHandler[h2] logger.addHandler[h2] logger.info["testing %d.. %d.. %d..", 1, 2, 3]
Một ví dụ
58 được đặt làm thuộc tính lớp ____276 cho_nameToLevel = { 'CRITICAL': CRITICAL, 'FATAL': FATAL, 'ERROR': ERROR, 'WARN': WARNING, 'WARNING': WARNING, 'INFO': INFO, 'DEBUG': DEBUG, 'NOTSET': NOTSET, } def _checkLevel[level]: if isinstance[level, int]: rv = level elif str[level] == level: if level not in _nameToLevel: raise ValueError["Unknown level: %r" % level] rv = _nameToLevel[level] else: raise TypeError["Level not an integer or a valid string: %r" % level] return rv
12. Điều này cuối cùng đi vào chơi trongCRITICAL = 50 FATAL = CRITICAL ERROR = 40 WARNING = 30 WARN = WARNING INFO = 20 DEBUG = 10 NOTSET = 0
78._nameToLevel = { 'CRITICAL': CRITICAL, 'FATAL': FATAL, 'ERROR': ERROR, 'WARN': WARNING, 'WARNING': WARNING, 'INFO': INFO, 'DEBUG': DEBUG, 'NOTSET': NOTSET, } def _checkLevel[level]: if isinstance[level, int]: rv = level elif str[level] == level: if level not in _nameToLevel: raise ValueError["Unknown level: %r" % level] rv = _nameToLevel[level] else: raise TypeError["Level not an integer or a valid string: %r" % level] return rv
76 thực hiện tất cả việc tạo thuận lợi cho việc tìm kiếm các trình ghi nhật ký hiện có với tên_nameToLevel = { 'CRITICAL': CRITICAL, 'FATAL': FATAL, 'ERROR': ERROR, 'WARN': WARNING, 'WARNING': WARNING, 'INFO': INFO, 'DEBUG': DEBUG, 'NOTSET': NOTSET, } def _checkLevel[level]: if isinstance[level, int]: rv = level elif str[level] == level: if level not in _nameToLevel: raise ValueError["Unknown level: %r" % level] rv = _nameToLevel[level] else: raise TypeError["Level not an integer or a valid string: %r" % level] return rv
80 và tạo chúng nếu chúng không tồn tại._nameToLevel = { 'CRITICAL': CRITICAL, 'FATAL': FATAL, 'ERROR': ERROR, 'WARN': WARNING, 'WARNING': WARNING, 'INFO': INFO, 'DEBUG': DEBUG, 'NOTSET': NOTSET, } def _checkLevel[level]: if isinstance[level, int]: rv = level elif str[level] == level: if level not in _nameToLevel: raise ValueError["Unknown level: %r" % level] rv = _nameToLevel[level] else: raise TypeError["Level not an integer or a valid string: %r" % level] return rv
Phân cấp logger
Tất cả mọi thứ là một đứa trẻ của
CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
93 trong không gian tên logger, và ý tôi là tất cả mọi thứ. Điều đó bao gồm các trình ghi nhật ký mà bạn chỉ định bản thân cũng như những người từ các thư viện của bên thứ ba mà bạn nhập.Hãy nhớ trước đó làm thế nào
CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
85 cho các trường hợp CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
16 của chúng tôi là 30 [_nameToLevel = {
'CRITICAL': CRITICAL,
'FATAL': FATAL,
'ERROR': ERROR,
'WARN': WARNING,
'WARNING': WARNING,
'INFO': INFO,
'DEBUG': DEBUG,
'NOTSET': NOTSET,
}
def _checkLevel[level]:
if isinstance[level, int]:
rv = level
elif str[level] == level:
if level not in _nameToLevel:
raise ValueError["Unknown level: %r" % level]
rv = _nameToLevel[level]
else:
raise TypeError["Level not an integer or a valid string: %r" % level]
return rv
20] mặc dù chúng tôi đã không đặt nó một cách rõ ràng? Điều đó bởi vì logger gốc nằm ở đầu phân cấp và cấp độ của nó là một dự phòng nếu bất kỳ logger lồng nhau nào có mức null là CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
91:>>>
CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
8Logic tương tự áp dụng cho việc tìm kiếm một trình xử lý logger. Việc tìm kiếm thực sự là một tìm kiếm theo thứ tự ngược lại trên cây của cha mẹ logger.
Một thiết kế đa tay
Phân cấp logger có vẻ gọn gàng trong lý thuyết, nhưng nó có lợi như thế nào trong thực tế?
Hãy cùng nghỉ ngơi khi khám phá mã
import logging
import sys
logger = logging.getLogger["pylog"]
logger.setLevel[logging.DEBUG]
h2 = logging.FileHandler[filename="/tmp/records.log"]
h2.setLevel[logging.INFO]
h2 = logging.StreamHandler[sys.stderr]
h2.setLevel[logging.ERROR]
logger.addHandler[h2]
logger.addHandler[h2]
logger.info["testing %d.. %d.. %d..", 1, 2, 3]
5 và đưa vào việc viết ứng dụng nhỏ của riêng chúng tôi, một người tận dụng phân cấp logger theo cách giảm mã nồi hơi và giữ cho mọi thứ có thể mở rộng nếu dự án CodeBase phát triển.Ở đây, cấu trúc dự án:
CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
9Don Tiết lo lắng về các chức năng chính của ứng dụng trong
_nameToLevel = {
'CRITICAL': CRITICAL,
'FATAL': FATAL,
'ERROR': ERROR,
'WARN': WARNING,
'WARNING': WARNING,
'INFO': INFO,
'DEBUG': DEBUG,
'NOTSET': NOTSET,
}
def _checkLevel[level]:
if isinstance[level, int]:
rv = level
elif str[level] == level:
if level not in _nameToLevel:
raise ValueError["Unknown level: %r" % level]
rv = _nameToLevel[level]
else:
raise TypeError["Level not an integer or a valid string: %r" % level]
return rv
87 và _nameToLevel = {
'CRITICAL': CRITICAL,
'FATAL': FATAL,
'ERROR': ERROR,
'WARN': WARNING,
'WARNING': WARNING,
'INFO': INFO,
'DEBUG': DEBUG,
'NOTSET': NOTSET,
}
def _checkLevel[level]:
if isinstance[level, int]:
rv = level
elif str[level] == level:
if level not in _nameToLevel:
raise ValueError["Unknown level: %r" % level]
rv = _nameToLevel[level]
else:
raise TypeError["Level not an integer or a valid string: %r" % level]
return rv
88. Những gì chúng tôi chú ý nhiều hơn ở đây là sự tương tác trong các đối tượng import logging
import sys
logger = logging.getLogger["pylog"]
logger.setLevel[logging.DEBUG]
h2 = logging.FileHandler[filename="/tmp/records.log"]
h2.setLevel[logging.INFO]
h2 = logging.StreamHandler[sys.stderr]
h2.setLevel[logging.ERROR]
logger.addHandler[h2]
logger.addHandler[h2]
logger.info["testing %d.. %d.. %d..", 1, 2, 3]
5 giữa các mô -đun trong _nameToLevel = {
'CRITICAL': CRITICAL,
'FATAL': FATAL,
'ERROR': ERROR,
'WARN': WARNING,
'WARNING': WARNING,
'INFO': INFO,
'DEBUG': DEBUG,
'NOTSET': NOTSET,
}
def _checkLevel[level]:
if isinstance[level, int]:
rv = level
elif str[level] == level:
if level not in _nameToLevel:
raise ValueError["Unknown level: %r" % level]
rv = _nameToLevel[level]
else:
raise TypeError["Level not an integer or a valid string: %r" % level]
return rv
90.Trong trường hợp này, hãy nói rằng bạn muốn thiết kế một thiết lập ghi nhật ký nhiều lần:
Mỗi mô -đun nhận được
16 với nhiều trình xử lý.CRITICAL = 50 FATAL = CRITICAL ERROR = 40 WARNING = 30 WARN = WARNING INFO = 20 DEBUG = 10 NOTSET = 0
Một số trình xử lý được chia sẻ giữa các trường hợp
16 khác nhau trong các mô -đun khác nhau. Các trình xử lý này chỉ quan tâm đến bộ lọc dựa trên cấp độ, chứ không phải mô-đun trong đó bản ghi nhật ký phát ra từ. Có một trình xử lý cho các tin nhắnCRITICAL = 50 FATAL = CRITICAL ERROR = 40 WARNING = 30 WARN = WARNING INFO = 20 DEBUG = 10 NOTSET = 0
23, một choCRITICAL = 50 FATAL = CRITICAL ERROR = 40 WARNING = 30 WARN = WARNING INFO = 20 DEBUG = 10 NOTSET = 0
24, một choCRITICAL = 50 FATAL = CRITICAL ERROR = 40 WARNING = 30 WARN = WARNING INFO = 20 DEBUG = 10 NOTSET = 0
20, v.v._nameToLevel = { 'CRITICAL': CRITICAL, 'FATAL': FATAL, 'ERROR': ERROR, 'WARN': WARNING, 'WARNING': WARNING, 'INFO': INFO, 'DEBUG': DEBUG, 'NOTSET': NOTSET, } def _checkLevel[level]: if isinstance[level, int]: rv = level elif str[level] == level: if level not in _nameToLevel: raise ValueError["Unknown level: %r" % level] rv = _nameToLevel[level] else: raise TypeError["Level not an integer or a valid string: %r" % level] return rv
Mỗi
16 cũng được gắn với một trình xử lý bổ sung khác mà chỉ nhận được các trường hợp ____129 từ LoneCRITICAL = 50 FATAL = CRITICAL ERROR = 40 WARNING = 30 WARN = WARNING INFO = 20 DEBUG = 10 NOTSET = 0
16 đó. Bạn có thể gọi đây là một trình xử lý tệp dựa trên mô-đun.CRITICAL = 50 FATAL = CRITICAL ERROR = 40 WARNING = 30 WARN = WARNING INFO = 20 DEBUG = 10 NOTSET = 0
Trực quan, những gì chúng tôi chụp cho sẽ trông giống như thế này:
Hai đối tượng màu ngọc lam là các trường hợp của
CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
12, được thiết lập với import threading
_lock = threading.RLock[]
def _acquireLock[]:
if _lock:
_lock.acquire[]
def _releaseLock[]:
if _lock:
_lock.release[]
00 cho mỗi mô -đun trong một gói. Mọi thứ khác là một ví dụ CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
13.Suy nghĩ đằng sau thiết kế này là nó đã được ngăn cách gọn gàng. Bạn có thể nhìn thuận tiện nhìn vào các tin nhắn đến từ một logger duy nhất hoặc xem tin nhắn ở một cấp độ nhất định và ở trên đến từ bất kỳ logger hoặc mô -đun nào.
Các thuộc tính của hệ thống phân cấp logger làm cho nó phù hợp để thiết lập bố cục tay cầm logger đa nhân này. Điều đó nghĩa là gì? Ở đây, một lời giải thích ngắn gọn từ tài liệu Django:
Tại sao hệ thống phân cấp lại quan trọng? Vâng, bởi vì loggers có thể được thiết lập để tuyên truyền các cuộc gọi đăng nhập của họ đến cha mẹ của họ. Theo cách này, bạn có thể xác định một bộ xử lý duy nhất ở gốc của cây logger và nắm bắt tất cả các cuộc gọi ghi nhật ký trong phần cây con của loggers. Một trình xử lý ghi nhật ký được xác định trong không gian tên
02 sẽ bắt tất cả các tin nhắn ghi nhật ký được phát hành trên loggersimport threading _lock = threading.RLock[] def _acquireLock[]: if _lock: _lock.acquire[] def _releaseLock[]: if _lock: _lock.release[]
03 vàimport threading _lock = threading.RLock[] def _acquireLock[]: if _lock: _lock.acquire[] def _releaseLock[]: if _lock: _lock.release[]
04. [Nguồn]import threading _lock = threading.RLock[] def _acquireLock[]: if _lock: _lock.acquire[] def _releaseLock[]: if _lock: _lock.release[]
Thuật ngữ tuyên truyền đề cập đến cách một logger tiếp tục bước lên chuỗi cha mẹ của mình đang tìm kiếm người xử lý. Thuộc tính
import threading
_lock = threading.RLock[]
def _acquireLock[]:
if _lock:
_lock.acquire[]
def _releaseLock[]:
if _lock:
_lock.release[]
05 là _nameToLevel = {
'CRITICAL': CRITICAL,
'FATAL': FATAL,
'ERROR': ERROR,
'WARN': WARNING,
'WARNING': WARNING,
'INFO': INFO,
'DEBUG': DEBUG,
'NOTSET': NOTSET,
}
def _checkLevel[level]:
if isinstance[level, int]:
rv = level
elif str[level] == level:
if level not in _nameToLevel:
raise ValueError["Unknown level: %r" % level]
rv = _nameToLevel[level]
else:
raise TypeError["Level not an integer or a valid string: %r" % level]
return rv
47 cho một phiên bản CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
12 theo mặc định:propagate refers to how a logger keeps walking up its chain of parents looking for handlers. The import threading
_lock = threading.RLock[]
def _acquireLock[]:
if _lock:
_lock.acquire[]
def _releaseLock[]:
if _lock:
_lock.release[]
05 attribute is _nameToLevel = {
'CRITICAL': CRITICAL,
'FATAL': FATAL,
'ERROR': ERROR,
'WARN': WARNING,
'WARNING': WARNING,
'INFO': INFO,
'DEBUG': DEBUG,
'NOTSET': NOTSET,
}
def _checkLevel[level]:
if isinstance[level, int]:
rv = level
elif str[level] == level:
if level not in _nameToLevel:
raise ValueError["Unknown level: %r" % level]
rv = _nameToLevel[level]
else:
raise TypeError["Level not an integer or a valid string: %r" % level]
return rv
47 for a CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
12
instance by default:>>>
_nameToLevel = {
'CRITICAL': CRITICAL,
'FATAL': FATAL,
'ERROR': ERROR,
'WARN': WARNING,
'WARNING': WARNING,
'INFO': INFO,
'DEBUG': DEBUG,
'NOTSET': NOTSET,
}
def _checkLevel[level]:
if isinstance[level, int]:
rv = level
elif str[level] == level:
if level not in _nameToLevel:
raise ValueError["Unknown level: %r" % level]
rv = _nameToLevel[level]
else:
raise TypeError["Level not an integer or a valid string: %r" % level]
return rv
0Logic tương tự áp dụng cho việc tìm kiếm một trình xử lý logger. Việc tìm kiếm thực sự là một tìm kiếm theo thứ tự ngược lại trên cây của cha mẹ logger.
_nameToLevel = {
'CRITICAL': CRITICAL,
'FATAL': FATAL,
'ERROR': ERROR,
'WARN': WARNING,
'WARNING': WARNING,
'INFO': INFO,
'DEBUG': DEBUG,
'NOTSET': NOTSET,
}
def _checkLevel[level]:
if isinstance[level, int]:
rv = level
elif str[level] == level:
if level not in _nameToLevel:
raise ValueError["Unknown level: %r" % level]
rv = _nameToLevel[level]
else:
raise TypeError["Level not an integer or a valid string: %r" % level]
return rv
1Một thiết kế đa tay
Phân cấp logger có vẻ gọn gàng trong lý thuyết, nhưng nó có lợi như thế nào trong thực tế?
Don Tiết lo lắng về các chức năng chính của ứng dụng trong 87 và 88. Những gì chúng tôi chú ý nhiều hơn ở đây là sự tương tác trong các đối tượng 5 giữa các mô -đun trong 90. | Trong trường hợp này, hãy nói rằng bạn muốn thiết kế một thiết lập ghi nhật ký nhiều lần: |
Mỗi mô -đun nhận được 16 với nhiều trình xử lý. | Một số trình xử lý được chia sẻ giữa các trường hợp 16 khác nhau trong các mô -đun khác nhau. Các trình xử lý này chỉ quan tâm đến bộ lọc dựa trên cấp độ, chứ không phải mô-đun trong đó bản ghi nhật ký phát ra từ. Có một trình xử lý cho các tin nhắn 23, một cho 24, một cho 20, v.v. |
Mỗi 16 cũng được gắn với một trình xử lý bổ sung khác mà chỉ nhận được các trường hợp ____129 từ Lone 16 đó. Bạn có thể gọi đây là một trình xử lý tệp dựa trên mô-đun. | Trực quan, những gì chúng tôi chụp cho sẽ trông giống như thế này: |
Một thiết kế ghi nhật ký nhiều người [hình ảnh: Real Python]
Hai đối tượng màu ngọc lam là các trường hợp của
CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
12, được thiết lập với import threading
_lock = threading.RLock[]
def _acquireLock[]:
if _lock:
_lock.acquire[]
def _releaseLock[]:
if _lock:
_lock.release[]
00 cho mỗi mô -đun trong một gói. Mọi thứ khác là một ví dụ CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
13._nameToLevel = {
'CRITICAL': CRITICAL,
'FATAL': FATAL,
'ERROR': ERROR,
'WARN': WARNING,
'WARNING': WARNING,
'INFO': INFO,
'DEBUG': DEBUG,
'NOTSET': NOTSET,
}
def _checkLevel[level]:
if isinstance[level, int]:
rv = level
elif str[level] == level:
if level not in _nameToLevel:
raise ValueError["Unknown level: %r" % level]
rv = _nameToLevel[level]
else:
raise TypeError["Level not an integer or a valid string: %r" % level]
return rv
2Mô -đun này được nhập khi gói
import threading
_lock = threading.RLock[]
def _acquireLock[]:
if _lock:
_lock.acquire[]
def _releaseLock[]:
if _lock:
_lock.release[]
02 được nhập. Bạn thêm một trình xử lý cho mỗi cấp độ trong CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
23 đến class Logger[Filterer]:
# ...
def getEffectiveLevel[self]:
logger = self
while logger:
if logger.level:
return logger.level
logger = logger.parent
return NOTSET
def isEnabledFor[self, level]:
try:
return self._cache[level]
except KeyError:
_acquireLock[]
if self.manager.disable >= level:
is_enabled = self._cache[level] = False
else:
is_enabled = self._cache[level] = level >= self.getEffectiveLevel[]
_releaseLock[]
return is_enabled
4, sau đó gắn nó vào một logger duy nhất ở đầu phân cấp.Bạn cũng xác định chức năng tiện ích thêm một
import threading
_lock = threading.RLock[]
def _acquireLock[]:
if _lock:
_lock.acquire[]
def _releaseLock[]:
if _lock:
_lock.release[]
32 vào logger, trong đó import threading
_lock = threading.RLock[]
def _acquireLock[]:
if _lock:
_lock.acquire[]
def _releaseLock[]:
if _lock:
_lock.release[]
33 của trình xử lý tương ứng với tên mô -đun nơi xác định logger. [Điều này giả sử logger được xác định với import threading
_lock = threading.RLock[]
def _acquireLock[]:
if _lock:
_lock.acquire[]
def _releaseLock[]:
if _lock:
_lock.release[]
12.]Sau đó, bạn có thể thêm một số thiết lập logger nồi hơi tối thiểu trong
_nameToLevel = {
'CRITICAL': CRITICAL,
'FATAL': FATAL,
'ERROR': ERROR,
'WARN': WARNING,
'WARNING': WARNING,
'INFO': INFO,
'DEBUG': DEBUG,
'NOTSET': NOTSET,
}
def _checkLevel[level]:
if isinstance[level, int]:
rv = level
elif str[level] == level:
if level not in _nameToLevel:
raise ValueError["Unknown level: %r" % level]
rv = _nameToLevel[level]
else:
raise TypeError["Level not an integer or a valid string: %r" % level]
return rv
88 và _nameToLevel = {
'CRITICAL': CRITICAL,
'FATAL': FATAL,
'ERROR': ERROR,
'WARN': WARNING,
'WARNING': WARNING,
'INFO': INFO,
'DEBUG': DEBUG,
'NOTSET': NOTSET,
}
def _checkLevel[level]:
if isinstance[level, int]:
rv = level
elif str[level] == level:
if level not in _nameToLevel:
raise ValueError["Unknown level: %r" % level]
rv = _nameToLevel[level]
else:
raise TypeError["Level not an integer or a valid string: %r" % level]
return rv
87. Lưu ý rằng bạn chỉ cần thêm một trình xử lý bổ sung với import threading
_lock = threading.RLock[]
def _acquireLock[]:
if _lock:
_lock.acquire[]
def _releaseLock[]:
if _lock:
_lock.release[]
37 từ [Pdb] l
1514 exc_info = [type[exc_info], exc_info, exc_info.__traceback__]
1515 elif not isinstance[exc_info, tuple]:
1516 exc_info = sys.exc_info[]
1517 record = self.makeRecord[self.name, level, fn, lno, msg, args,
1518 exc_info, func, extra, sinfo]
1519 -> self.handle[record]
1520
1521 def handle[self, record]:
1522 """
1523 Call the handlers for the specified record.
1524
[Pdb] from pprint import pprint
[Pdb] pprint[vars[record]]
{'args': [],
'created': 1550671851.660067,
'exc_info': None,
'exc_text': None,
'filename': '',
'funcName': 'f',
'levelname': 'ERROR',
'levelno': 40,
'lineno': 2,
'module': '',
'msecs': 660.067081451416,
'msg': 'bad vibes',
'name': 'root',
'pathname': '',
'process': 2360,
'processName': 'MainProcess',
'relativeCreated': 295145.5490589142,
'stack_info': None,
'thread': 4372293056,
'threadName': 'MainThread'}
6. Bạn không cần phải lo lắng về các trình xử lý định hướng cấp độ vì họ đã được thêm vào logger cha mẹ của họ có tên import threading
_lock = threading.RLock[]
def _acquireLock[]:
if _lock:
_lock.acquire[]
def _releaseLock[]:
if _lock:
_lock.release[]
19:_nameToLevel = {
'CRITICAL': CRITICAL,
'FATAL': FATAL,
'ERROR': ERROR,
'WARN': WARNING,
'WARNING': WARNING,
'INFO': INFO,
'DEBUG': DEBUG,
'NOTSET': NOTSET,
}
def _checkLevel[level]:
if isinstance[level, int]:
rv = level
elif str[level] == level:
if level not in _nameToLevel:
raise ValueError["Unknown level: %r" % level]
rv = _nameToLevel[level]
else:
raise TypeError["Level not an integer or a valid string: %r" % level]
return rv
3Ở đây, ____ ____287:
_nameToLevel = {
'CRITICAL': CRITICAL,
'FATAL': FATAL,
'ERROR': ERROR,
'WARN': WARNING,
'WARNING': WARNING,
'INFO': INFO,
'DEBUG': DEBUG,
'NOTSET': NOTSET,
}
def _checkLevel[level]:
if isinstance[level, int]:
rv = level
elif str[level] == level:
if level not in _nameToLevel:
raise ValueError["Unknown level: %r" % level]
rv = _nameToLevel[level]
else:
raise TypeError["Level not an integer or a valid string: %r" % level]
return rv
4Hãy cùng xem cách tất cả những điều này hoạt động cùng nhau từ một phiên Python mới:
>>>
_nameToLevel = {
'CRITICAL': CRITICAL,
'FATAL': FATAL,
'ERROR': ERROR,
'WARN': WARNING,
'WARNING': WARNING,
'INFO': INFO,
'DEBUG': DEBUG,
'NOTSET': NOTSET,
}
def _checkLevel[level]:
if isinstance[level, int]:
rv = level
elif str[level] == level:
if level not in _nameToLevel:
raise ValueError["Unknown level: %r" % level]
rv = _nameToLevel[level]
else:
raise TypeError["Level not an integer or a valid string: %r" % level]
return rv
5Bạn sẽ thấy trong các tệp nhật ký kết quả mà hệ thống lọc của chúng tôi hoạt động như dự định. Trình xử lý định hướng mô-đun hướng một logger đến một tệp cụ thể, trong khi trình xử lý định hướng cấp độ trực tiếp nhiều trình ghi nhật ký đến một tệp khác:
_nameToLevel = {
'CRITICAL': CRITICAL,
'FATAL': FATAL,
'ERROR': ERROR,
'WARN': WARNING,
'WARNING': WARNING,
'INFO': INFO,
'DEBUG': DEBUG,
'NOTSET': NOTSET,
}
def _checkLevel[level]:
if isinstance[level, int]:
rv = level
elif str[level] == level:
if level not in _nameToLevel:
raise ValueError["Unknown level: %r" % level]
rv = _nameToLevel[level]
else:
raise TypeError["Level not an integer or a valid string: %r" % level]
return rv
6Một nhược điểm đáng nói là thiết kế này giới thiệu rất nhiều dự phòng. Một ví dụ
CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
29 có thể đi đến không dưới sáu tệp. Đó cũng là một số lượng tệp I/O không đáng kể có thể cộng vào một ứng dụng quan trọng hiệu suất.Bây giờ, bạn đã thấy một ví dụ thực tế, hãy để chuyển đổi bánh răng và đi sâu vào một nguồn nhầm lẫn có thể xảy ra trong
import logging
import sys
logger = logging.getLogger["pylog"]
logger.setLevel[logging.DEBUG]
h2 = logging.FileHandler[filename="/tmp/records.log"]
h2.setLevel[logging.INFO]
h2 = logging.StreamHandler[sys.stderr]
h2.setLevel[logging.ERROR]
logger.addHandler[h2]
logger.addHandler[h2]
logger.info["testing %d.. %d.. %d..", 1, 2, 3]
5.Tại sao không có tin nhắn nhật ký của tôi đi đâu? Tình trạng khó xử
Có hai tình huống phổ biến với
import logging
import sys
logger = logging.getLogger["pylog"]
logger.setLevel[logging.DEBUG]
h2 = logging.FileHandler[filename="/tmp/records.log"]
h2.setLevel[logging.INFO]
h2 = logging.StreamHandler[sys.stderr]
h2.setLevel[logging.ERROR]
logger.addHandler[h2]
logger.addHandler[h2]
logger.info["testing %d.. %d.. %d..", 1, 2, 3]
5 khi nó dễ bị vấp ngã:- Bạn đã đăng nhập một tin nhắn dường như không đi đến đâu và bạn không chắc tại sao.
- Thay vì bị đàn áp, một tin nhắn nhật ký xuất hiện ở một nơi mà bạn đã không mong đợi.
Mỗi trong số này có một hoặc hai lý do thường được liên kết với nó.
Bạn đã đăng nhập một tin nhắn dường như không đi đến đâu và bạn không chắc tại sao.
Thay vì bị đàn áp, một tin nhắn nhật ký xuất hiện ở một nơi mà bạn đã không mong đợi.effective level of a logger for which you don’t otherwise set a custom level is
_nameToLevel = {
'CRITICAL': CRITICAL,
'FATAL': FATAL,
'ERROR': ERROR,
'WARN': WARNING,
'WARNING': WARNING,
'INFO': INFO,
'DEBUG': DEBUG,
'NOTSET': NOTSET,
}
def _checkLevel[level]:
if isinstance[level, int]:
rv = level
elif str[level] == level:
if level not in _nameToLevel:
raise ValueError["Unknown level: %r" % level]
rv = _nameToLevel[level]
else:
raise TypeError["Level not an integer or a valid string: %r" % level]
return rv
20, because a logger will walk up its hierarchy until it finds the root logger with its own _nameToLevel = {
'CRITICAL': CRITICAL,
'FATAL': FATAL,
'ERROR': ERROR,
'WARN': WARNING,
'WARNING': WARNING,
'INFO': INFO,
'DEBUG': DEBUG,
'NOTSET': NOTSET,
}
def _checkLevel[level]:
if isinstance[level, int]:
rv = level
elif str[level] == level:
if level not in _nameToLevel:
raise ValueError["Unknown level: %r" % level]
rv = _nameToLevel[level]
else:
raise TypeError["Level not an integer or a valid string: %r" % level]
return rv
20 level:>>>
_nameToLevel = {
'CRITICAL': CRITICAL,
'FATAL': FATAL,
'ERROR': ERROR,
'WARN': WARNING,
'WARNING': WARNING,
'INFO': INFO,
'DEBUG': DEBUG,
'NOTSET': NOTSET,
}
def _checkLevel[level]:
if isinstance[level, int]:
rv = level
elif str[level] == level:
if level not in _nameToLevel:
raise ValueError["Unknown level: %r" % level]
rv = _nameToLevel[level]
else:
raise TypeError["Level not an integer or a valid string: %r" % level]
return rv
7Bạn sẽ thấy trong các tệp nhật ký kết quả mà hệ thống lọc của chúng tôi hoạt động như dự định. Trình xử lý định hướng mô-đun hướng một logger đến một tệp cụ thể, trong khi trình xử lý định hướng cấp độ trực tiếp nhiều trình ghi nhật ký đến một tệp khác:
Thay vì bị đàn áp, một tin nhắn nhật ký xuất hiện ở một nơi mà bạn đã không mong đợi.
Mỗi trong số này có một hoặc hai lý do thường được liên kết với nó.
Don Tiết quên rằng mức độ hiệu quả của một logger mà bạn không nên đặt cấp độ tùy chỉnh là
_nameToLevel = {
'CRITICAL': CRITICAL,
'FATAL': FATAL,
'ERROR': ERROR,
'WARN': WARNING,
'WARNING': WARNING,
'INFO': INFO,
'DEBUG': DEBUG,
'NOTSET': NOTSET,
}
def _checkLevel[level]:
if isinstance[level, int]:
rv = level
elif str[level] == level:
if level not in _nameToLevel:
raise ValueError["Unknown level: %r" % level]
rv = _nameToLevel[level]
else:
raise TypeError["Level not an integer or a valid string: %r" % level]
return rv
20, bởi vì một bộ ghi sẽ đi lên thứ bậc của nó cho đến khi tìm thấy bộ ghi gốc với mức ____220 của riêng mình:_nameToLevel = {
'CRITICAL': CRITICAL,
'FATAL': FATAL,
'ERROR': ERROR,
'WARN': WARNING,
'WARNING': WARNING,
'INFO': INFO,
'DEBUG': DEBUG,
'NOTSET': NOTSET,
}
def _checkLevel[level]:
if isinstance[level, int]:
rv = level
elif str[level] == level:
if level not in _nameToLevel:
raise ValueError["Unknown level: %r" % level]
rv = _nameToLevel[level]
else:
raise TypeError["Level not an integer or a valid string: %r" % level]
return rv
8Vì mặc định này, cuộc gọi
import threading
_lock = threading.RLock[]
def _acquireLock[]:
if _lock:
_lock.acquire[]
def _releaseLock[]:
if _lock:
_lock.release[]
46 không đi đến đâu._nameToLevel = {
'CRITICAL': CRITICAL,
'FATAL': FATAL,
'ERROR': ERROR,
'WARN': WARNING,
'WARNING': WARNING,
'INFO': INFO,
'DEBUG': DEBUG,
'NOTSET': NOTSET,
}
def _checkLevel[level]:
if isinstance[level, int]:
rv = level
elif str[level] == level:
if level not in _nameToLevel:
raise ValueError["Unknown level: %r" % level]
rv = _nameToLevel[level]
else:
raise TypeError["Level not an integer or a valid string: %r" % level]
return rv
9Khi bạn xác định
CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
16 của mình ở trên, bạn đã không thêm bất kỳ trình xử lý nào vào đó. Vì vậy, tại sao nó viết vào bảng điều khiển?Lý do cho điều này là
import logging
import sys
logger = logging.getLogger["pylog"]
logger.setLevel[logging.DEBUG]
h2 = logging.FileHandler[filename="/tmp/records.log"]
h2.setLevel[logging.INFO]
h2 = logging.StreamHandler[sys.stderr]
h2.setLevel[logging.ERROR]
logger.addHandler[h2]
logger.addHandler[h2]
logger.info["testing %d.. %d.. %d..", 1, 2, 3]
5 Sneaking sử dụng một trình xử lý có tên là import threading
_lock = threading.RLock[]
def _acquireLock[]:
if _lock:
_lock.acquire[]
def _releaseLock[]:
if _lock:
_lock.release[]
49 ghi vào CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
35 nếu không tìm thấy người xử lý nào khác:Điều này khởi động khi một logger đi tìm trình xử lý của nó:
>>>
import threading
_lock = threading.RLock[]
def _acquireLock[]:
if _lock:
_lock.acquire[]
def _releaseLock[]:
if _lock:
_lock.release[]
0Bạn sẽ thấy trong các tệp nhật ký kết quả mà hệ thống lọc của chúng tôi hoạt động như dự định. Trình xử lý định hướng mô-đun hướng một logger đến một tệp cụ thể, trong khi trình xử lý định hướng cấp độ trực tiếp nhiều trình ghi nhật ký đến một tệp khác:
Một nhược điểm đáng nói là thiết kế này giới thiệu rất nhiều dự phòng. Một ví dụ
CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
29 có thể đi đến không dưới sáu tệp. Đó cũng là một số lượng tệp I/O không đáng kể có thể cộng vào một ứng dụng quan trọng hiệu suất.>>>
import threading
_lock = threading.RLock[]
def _acquireLock[]:
if _lock:
_lock.acquire[]
def _releaseLock[]:
if _lock:
_lock.release[]
1Bạn sẽ thấy trong các tệp nhật ký kết quả mà hệ thống lọc của chúng tôi hoạt động như dự định. Trình xử lý định hướng mô-đun hướng một logger đến một tệp cụ thể, trong khi trình xử lý định hướng cấp độ trực tiếp nhiều trình ghi nhật ký đến một tệp khác:
>>>
import threading
_lock = threading.RLock[]
def _acquireLock[]:
if _lock:
_lock.acquire[]
def _releaseLock[]:
if _lock:
_lock.release[]
2Bạn sẽ thấy trong các tệp nhật ký kết quả mà hệ thống lọc của chúng tôi hoạt động như dự định. Trình xử lý định hướng mô-đun hướng một logger đến một tệp cụ thể, trong khi trình xử lý định hướng cấp độ trực tiếp nhiều trình ghi nhật ký đến một tệp khác:
Một nhược điểm đáng nói là thiết kế này giới thiệu rất nhiều dự phòng. Một ví dụ
CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
29 có thể đi đến không dưới sáu tệp. Đó cũng là một số lượng tệp I/O không đáng kể có thể cộng vào một ứng dụng quan trọng hiệu suất.>>>
import threading
_lock = threading.RLock[]
def _acquireLock[]:
if _lock:
_lock.acquire[]
def _releaseLock[]:
if _lock:
_lock.release[]
3Bạn sẽ thấy trong các tệp nhật ký kết quả mà hệ thống lọc của chúng tôi hoạt động như dự định. Trình xử lý định hướng mô-đun hướng một logger đến một tệp cụ thể, trong khi trình xử lý định hướng cấp độ trực tiếp nhiều trình ghi nhật ký đến một tệp khác:lazily rather than greedily. Here’s what that means.
Một nhược điểm đáng nói là thiết kế này giới thiệu rất nhiều dự phòng. Một ví dụ
CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
29 có thể đi đến không dưới sáu tệp. Đó cũng là một số lượng tệp I/O không đáng kể có thể cộng vào một ứng dụng quan trọng hiệu suất.import threading
_lock = threading.RLock[]
def _acquireLock[]:
if _lock:
_lock.acquire[]
def _releaseLock[]:
if _lock:
_lock.release[]
4Bây giờ, bạn đã thấy một ví dụ thực tế, hãy để chuyển đổi bánh răng và đi sâu vào một nguồn nhầm lẫn có thể xảy ra trong
import logging
import sys
logger = logging.getLogger["pylog"]
logger.setLevel[logging.DEBUG]
h2 = logging.FileHandler[filename="/tmp/records.log"]
h2.setLevel[logging.INFO]
h2 = logging.StreamHandler[sys.stderr]
h2.setLevel[logging.ERROR]
logger.addHandler[h2]
logger.addHandler[h2]
logger.info["testing %d.. %d.. %d..", 1, 2, 3]
5.Tại sao không có tin nhắn nhật ký của tôi đi đâu? Tình trạng khó xử
import threading
_lock = threading.RLock[]
def _acquireLock[]:
if _lock:
_lock.acquire[]
def _releaseLock[]:
if _lock:
_lock.release[]
5Có hai tình huống phổ biến với
import logging
import sys
logger = logging.getLogger["pylog"]
logger.setLevel[logging.DEBUG]
h2 = logging.FileHandler[filename="/tmp/records.log"]
h2.setLevel[logging.INFO]
h2 = logging.StreamHandler[sys.stderr]
h2.setLevel[logging.ERROR]
logger.addHandler[h2]
logger.addHandler[h2]
logger.info["testing %d.. %d.. %d..", 1, 2, 3]
5 khi nó dễ bị vấp ngã:Vì sao vấn đề này? Các cuộc gọi ghi nhật ký lặp đi lặp lại có thể làm giảm hiệu suất thời gian chạy một chút, nhưng gói
import logging
import sys
logger = logging.getLogger["pylog"]
logger.setLevel[logging.DEBUG]
h2 = logging.FileHandler[filename="/tmp/records.log"]
h2.setLevel[logging.INFO]
h2 = logging.StreamHandler[sys.stderr]
h2.setLevel[logging.ERROR]
logger.addHandler[h2]
logger.addHandler[h2]
logger.info["testing %d.. %d.. %d..", 1, 2, 3]
5 thực hiện tốt nhất để kiểm soát điều đó và kiểm tra nó. Bằng cách không hợp nhất chuỗi định dạng với các đối số của nó ngay lập tức, import logging
import sys
logger = logging.getLogger["pylog"]
logger.setLevel[logging.DEBUG]
h2 = logging.FileHandler[filename="/tmp/records.log"]
h2.setLevel[logging.INFO]
h2 = logging.StreamHandler[sys.stderr]
h2.setLevel[logging.ERROR]
logger.addHandler[h2]
logger.addHandler[h2]
logger.info["testing %d.. %d.. %d..", 1, 2, 3]
5 đang trì hoãn định dạng chuỗi cho đến khi CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
29 được yêu cầu bởi CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
13.Điều này xảy ra trong ____378, vì vậy chỉ sau khi
import logging
import sys
logger = logging.getLogger["pylog"]
logger.setLevel[logging.DEBUG]
h2 = logging.FileHandler[filename="/tmp/records.log"]
h2.setLevel[logging.INFO]
h2 = logging.StreamHandler[sys.stderr]
h2.setLevel[logging.ERROR]
logger.addHandler[h2]
logger.addHandler[h2]
logger.info["testing %d.. %d.. %d..", 1, 2, 3]
5 thấy rằng CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
29 sẽ thực sự được chuyển cho một người xử lý, nó mới trở thành bản thân được hợp nhất đầy đủ.Tất cả những gì có nghĩa là gói
import logging
import sys
logger = logging.getLogger["pylog"]
logger.setLevel[logging.DEBUG]
h2 = logging.FileHandler[filename="/tmp/records.log"]
h2.setLevel[logging.INFO]
h2 = logging.StreamHandler[sys.stderr]
h2.setLevel[logging.ERROR]
logger.addHandler[h2]
logger.addHandler[h2]
logger.info["testing %d.. %d.. %d..", 1, 2, 3]
5 làm cho một số tối ưu hóa hiệu suất rất tinh chỉnh ở đúng nơi. Điều này có vẻ giống như Minutia, nhưng nếu bạn thực hiện cùng một import threading
_lock = threading.RLock[]
def _acquireLock[]:
if _lock:
_lock.acquire[]
def _releaseLock[]:
if _lock:
_lock.release[]
82 gọi một triệu lần trong một vòng lặp và import threading
_lock = threading.RLock[]
def _acquireLock[]:
if _lock:
_lock.acquire[]
def _releaseLock[]:
if _lock:
_lock.release[]
69 là các cuộc gọi chức năng, thì bản chất lười biếng của cách import logging
import sys
logger = logging.getLogger["pylog"]
logger.setLevel[logging.DEBUG]
h2 = logging.FileHandler[filename="/tmp/records.log"]
h2.setLevel[logging.INFO]
h2 = logging.StreamHandler[sys.stderr]
h2.setLevel[logging.ERROR]
logger.addHandler[h2]
logger.addHandler[h2]
logger.info["testing %d.. %d.. %d..", 1, 2, 3]
5 định dạng chuỗi có thể tạo ra sự khác biệt.Trước khi thực hiện bất kỳ sự hợp nhất nào của
import threading
_lock = threading.RLock[]
def _acquireLock[]:
if _lock:
_lock.acquire[]
def _releaseLock[]:
if _lock:
_lock.release[]
60 và import threading
_lock = threading.RLock[]
def _acquireLock[]:
if _lock:
_lock.acquire[]
def _releaseLock[]:
if _lock:
_lock.release[]
69, một ví dụ CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
12 sẽ kiểm tra CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
84 của nó để xem liệu việc hợp nhất có nên được thực hiện ngay từ đầu không.Chức năng so với phương pháp
Về phía dưới của
[Pdb] l
1514 exc_info = [type[exc_info], exc_info, exc_info.__traceback__]
1515 elif not isinstance[exc_info, tuple]:
1516 exc_info = sys.exc_info[]
1517 record = self.makeRecord[self.name, level, fn, lno, msg, args,
1518 exc_info, func, extra, sinfo]
1519 -> self.handle[record]
1520
1521 def handle[self, record]:
1522 """
1523 Call the handlers for the specified record.
1524
[Pdb] from pprint import pprint
[Pdb] pprint[vars[record]]
{'args': [],
'created': 1550671851.660067,
'exc_info': None,
'exc_text': None,
'filename': '',
'funcName': 'f',
'levelname': 'ERROR',
'levelno': 40,
'lineno': 2,
'module': '',
'msecs': 660.067081451416,
'msg': 'bad vibes',
'name': 'root',
'pathname': '',
'process': 2360,
'processName': 'MainProcess',
'relativeCreated': 295145.5490589142,
'stack_info': None,
'thread': 4372293056,
'threadName': 'MainThread'}
5, hãy đặt các chức năng cấp độ mô-đun được quảng cáo lên phía trước trong API công khai của import logging
import sys
logger = logging.getLogger["pylog"]
logger.setLevel[logging.DEBUG]
h2 = logging.FileHandler[filename="/tmp/records.log"]
h2.setLevel[logging.INFO]
h2 = logging.StreamHandler[sys.stderr]
h2.setLevel[logging.ERROR]
logger.addHandler[h2]
logger.addHandler[h2]
logger.info["testing %d.. %d.. %d..", 1, 2, 3]
5. Bạn đã thấy các phương pháp CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
12 như import threading
_lock = threading.RLock[]
def _acquireLock[]:
if _lock:
_lock.acquire[]
def _releaseLock[]:
if _lock:
_lock.release[]
46, import threading
_lock = threading.RLock[]
def _acquireLock[]:
if _lock:
_lock.acquire[]
def _releaseLock[]:
if _lock:
_lock.release[]
93 và import threading
_lock = threading.RLock[]
def _acquireLock[]:
if _lock:
_lock.acquire[]
def _releaseLock[]:
if _lock:
_lock.release[]
94. Các chức năng cấp cao nhất là các trình bao bọc xung quanh các phương thức tương ứng cùng tên, nhưng chúng có hai tính năng quan trọng:Họ luôn gọi phương thức tương ứng của họ từ logger gốc,
93.CRITICAL = 50 FATAL = CRITICAL ERROR = 40 WARNING = 30 WARN = WARNING INFO = 20 DEBUG = 10 NOTSET = 0
Trước khi gọi các phương thức logger gốc, họ gọi
55 không có đối số nếuimport threading _lock = threading.RLock[] def _acquireLock[]: if _lock: _lock.acquire[] def _releaseLock[]: if _lock: _lock.release[]
93 không có trình xử lý. Như bạn đã thấy trước đó, đó là cuộc gọi này đặt ra một trình xử lýCRITICAL = 50 FATAL = CRITICAL ERROR = 40 WARNING = 30 WARN = WARNING INFO = 20 DEBUG = 10 NOTSET = 0
76 cho bộ ghi gốc.CRITICAL = 50 FATAL = CRITICAL ERROR = 40 WARNING = 30 WARN = WARNING INFO = 20 DEBUG = 10 NOTSET = 0
Để minh họa, ở đây, ____ ____151:
import threading
_lock = threading.RLock[]
def _acquireLock[]:
if _lock:
_lock.acquire[]
def _releaseLock[]:
if _lock:
_lock.release[]
6Bạn sẽ tìm thấy cùng một mẫu cho
import threading
_lock = threading.RLock[]
def _acquireLock[]:
if _lock:
_lock.acquire[]
def _releaseLock[]:
if _lock:
_lock.release[]
82, import threading
_lock = threading.RLock[]
def _acquireLock[]:
if _lock:
_lock.acquire[]
def _releaseLock[]:
if _lock:
_lock.release[]
53 và các mẫu khác là tốt. Truy tìm chuỗi các lệnh là thú vị. Cuối cùng, bạn sẽ kết thúc ở cùng một nơi, đó là nơi được gọi là object
│
├── LogRecord
├── Filterer
│ ├── Logger
│ │ └── RootLogger
│ └── Handler
│ ├── StreamHandler
│ └── NullHandler
├── Filter
└── Manager
02 bên trong.Các cuộc gọi đến
object
│
├── LogRecord
├── Filterer
│ ├── Logger
│ │ └── RootLogger
│ └── Handler
│ ├── StreamHandler
│ └── NullHandler
├── Filter
└── Manager
03, object
│
├── LogRecord
├── Filterer
│ ├── Logger
│ │ └── RootLogger
│ └── Handler
│ ├── StreamHandler
│ └── NullHandler
├── Filter
└── Manager
04, object
│
├── LogRecord
├── Filterer
│ ├── Logger
│ │ └── RootLogger
│ └── Handler
│ ├── StreamHandler
│ └── NullHandler
├── Filter
└── Manager
05 và các chức năng dựa trên cấp độ khác tất cả các chức năng đến đây. object
│
├── LogRecord
├── Filterer
│ ├── Logger
│ │ └── RootLogger
│ └── Handler
│ ├── StreamHandler
│ └── NullHandler
├── Filter
└── Manager
06 chủ yếu có hai mục đích:Gọi
07: Tạo một thể hiệnobject │ ├── LogRecord ├── Filterer │ ├── Logger │ │ └── RootLogger │ └── Handler │ ├── StreamHandler │ └── NullHandler ├── Filter └── Manager
29 từCRITICAL = 50 FATAL = CRITICAL ERROR = 40 WARNING = 30 WARN = WARNING INFO = 20 DEBUG = 10 NOTSET = 0
60 và các đối số khác mà bạn chuyển cho nó. Make aimport threading _lock = threading.RLock[] def _acquireLock[]: if _lock: _lock.acquire[] def _releaseLock[]: if _lock: _lock.release[]
29 instance from theCRITICAL = 50 FATAL = CRITICAL ERROR = 40 WARNING = 30 WARN = WARNING INFO = 20 DEBUG = 10 NOTSET = 0
60 and other arguments you pass to it.import threading _lock = threading.RLock[] def _acquireLock[]: if _lock: _lock.acquire[] def _releaseLock[]: if _lock: _lock.release[]
Gọi
10: Điều này xác định những gì thực sự được thực hiện với hồ sơ. Nó được gửi ở đâu? Nó làm cho nó ở đó hoặc được lọc ra? This determines what actually gets done with the record. Where does it get sent? Does it make it there or get filtered out?object │ ├── LogRecord ├── Filterer │ ├── Logger │ │ └── RootLogger │ └── Handler │ ├── StreamHandler │ └── NullHandler ├── Filter └── Manager
Ở đây, toàn bộ quá trình trong một sơ đồ:
Bạn cũng có thể theo dõi ngăn xếp cuộc gọi với
CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
52.>>>
import threading
_lock = threading.RLock[]
def _acquireLock[]:
if _lock:
_lock.acquire[]
def _releaseLock[]:
if _lock:
_lock.release[]
7object
│
├── LogRecord
├── Filterer
│ ├── Logger
│ │ └── RootLogger
│ └── Handler
│ ├── StreamHandler
│ └── NullHandler
├── Filter
└── Manager
12 thực sự làm gì?
object
│
├── LogRecord
├── Filterer
│ ├── Logger
│ │ └── RootLogger
│ └── Handler
│ ├── StreamHandler
│ └── NullHandler
├── Filter
└── Manager
Cũng ẩn trong phần này của mã nguồn là cấp cao nhất
object
│
├── LogRecord
├── Filterer
│ ├── Logger
│ │ └── RootLogger
│ └── Handler
│ ├── StreamHandler
│ └── NullHandler
├── Filter
└── Manager
12, kết thúc object
│
├── LogRecord
├── Filterer
│ ├── Logger
│ │ └── RootLogger
│ └── Handler
│ ├── StreamHandler
│ └── NullHandler
├── Filter
└── Manager
14:import threading
_lock = threading.RLock[]
def _acquireLock[]:
if _lock:
_lock.acquire[]
def _releaseLock[]:
if _lock:
_lock.release[]
8Đây là điểm nhập cảnh để thực thi thiết kế Singleton Logger:
Nếu bạn chỉ định
15, thìobject │ ├── LogRecord ├── Filterer │ ├── Logger │ │ └── RootLogger │ └── Handler │ ├── StreamHandler │ └── NullHandler ├── Filter └── Manager
16 bên dưới sẽ tra cứuobject │ ├── LogRecord ├── Filterer │ ├── Logger │ │ └── RootLogger │ └── Handler │ ├── StreamHandler │ └── NullHandler ├── Filter └── Manager
8 trên chuỗiclass Logger[Filterer]: # ... def getEffectiveLevel[self]: logger = self while logger: if logger.level: return logger.level logger = logger.parent return NOTSET def isEnabledFor[self, level]: try: return self._cache[level] except KeyError: _acquireLock[] if self.manager.disable >= level: is_enabled = self._cache[level] = False else: is_enabled = self._cache[level] = level >= self.getEffectiveLevel[] _releaseLock[] return is_enabled
15. Những gì điều này xuất hiện là một tra cứu trongobject │ ├── LogRecord ├── Filterer │ ├── Logger │ │ └── RootLogger │ └── Handler │ ├── StreamHandler │ └── NullHandler ├── Filter └── Manager
19 củaobject │ ├── LogRecord ├── Filterer │ ├── Logger │ │ └── RootLogger │ └── Handler │ ├── StreamHandler │ └── NullHandler ├── Filter └── Manager
20. Đây là một từ điển của tất cả các trình ghi nhật ký đã đăng ký, bao gồm các trường hợpobject │ ├── LogRecord ├── Filterer │ ├── Logger │ │ └── RootLogger │ └── Handler │ ├── StreamHandler │ └── NullHandler ├── Filter └── Manager
21 trung gian được tạo khi bạn tham chiếu một logger từ xa trong hệ thống phân cấp trước khi tham khảo cha mẹ của nó.object │ ├── LogRecord ├── Filterer │ ├── Logger │ │ └── RootLogger │ └── Handler │ ├── StreamHandler │ └── NullHandler ├── Filter └── Manager
Nếu không,
93 được trả lại. Chỉ có một ____ 193, ví dụ củaCRITICAL = 50 FATAL = CRITICAL ERROR = 40 WARNING = 30 WARN = WARNING INFO = 20 DEBUG = 10 NOTSET = 0
68 đã thảo luận ở trên._nameToLevel = { 'CRITICAL': CRITICAL, 'FATAL': FATAL, 'ERROR': ERROR, 'WARN': WARNING, 'WARNING': WARNING, 'INFO': INFO, 'DEBUG': DEBUG, 'NOTSET': NOTSET, } def _checkLevel[level]: if isinstance[level, int]: rv = level elif str[level] == level: if level not in _nameToLevel: raise ValueError["Unknown level: %r" % level] rv = _nameToLevel[level] else: raise TypeError["Level not an integer or a valid string: %r" % level] return rv
Tính năng này là những gì nằm đằng sau một mẹo có thể cho phép bạn nhìn trộm tất cả các loggers đã đăng ký:
>>>
import threading
_lock = threading.RLock[]
def _acquireLock[]:
if _lock:
_lock.acquire[]
def _releaseLock[]:
if _lock:
_lock.release[]
9object
│
├── LogRecord
├── Filterer
│ ├── Logger
│ │ └── RootLogger
│ └── Handler
│ ├── StreamHandler
│ └── NullHandler
├── Filter
└── Manager
12 thực sự làm gì?Cũng ẩn trong phần này của mã nguồn là cấp cao nhất
object
│
├── LogRecord
├── Filterer
│ ├── Logger
│ │ └── RootLogger
│ └── Handler
│ ├── StreamHandler
│ └── NullHandler
├── Filter
└── Manager
12, kết thúc object
│
├── LogRecord
├── Filterer
│ ├── Logger
│ │ └── RootLogger
│ └── Handler
│ ├── StreamHandler
│ └── NullHandler
├── Filter
└── Manager
14:Đây là điểm nhập cảnh để thực thi thiết kế Singleton Logger:
object
│
├── LogRecord
├── Filterer
│ ├── Logger
│ │ └── RootLogger
│ └── Handler
│ ├── StreamHandler
│ └── NullHandler
├── Filter
└── Manager
0Nếu bạn chỉ định
object
│
├── LogRecord
├── Filterer
│ ├── Logger
│ │ └── RootLogger
│ └── Handler
│ ├── StreamHandler
│ └── NullHandler
├── Filter
└── Manager
15, thì object
│
├── LogRecord
├── Filterer
│ ├── Logger
│ │ └── RootLogger
│ └── Handler
│ ├── StreamHandler
│ └── NullHandler
├── Filter
└── Manager
16 bên dưới sẽ tra cứu class Logger[Filterer]:
# ...
def getEffectiveLevel[self]:
logger = self
while logger:
if logger.level:
return logger.level
logger = logger.parent
return NOTSET
def isEnabledFor[self, level]:
try:
return self._cache[level]
except KeyError:
_acquireLock[]
if self.manager.disable >= level:
is_enabled = self._cache[level] = False
else:
is_enabled = self._cache[level] = level >= self.getEffectiveLevel[]
_releaseLock[]
return is_enabled
8 trên chuỗi object
│
├── LogRecord
├── Filterer
│ ├── Logger
│ │ └── RootLogger
│ └── Handler
│ ├── StreamHandler
│ └── NullHandler
├── Filter
└── Manager
15. Những gì điều này xuất hiện là một tra cứu trong object
│
├── LogRecord
├── Filterer
│ ├── Logger
│ │ └── RootLogger
│ └── Handler
│ ├── StreamHandler
│ └── NullHandler
├── Filter
└── Manager
19 của object
│
├── LogRecord
├── Filterer
│ ├── Logger
│ │ └── RootLogger
│ └── Handler
│ ├── StreamHandler
│ └── NullHandler
├── Filter
└── Manager
20. Đây là một từ điển của tất cả các trình ghi nhật ký đã đăng ký, bao gồm các trường hợp object
│
├── LogRecord
├── Filterer
│ ├── Logger
│ │ └── RootLogger
│ └── Handler
│ ├── StreamHandler
│ └── NullHandler
├── Filter
└── Manager
21 trung gian được tạo khi bạn tham chiếu một logger từ xa trong hệ thống phân cấp trước khi tham khảo cha mẹ của nó.Nếu không,
CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
93 được trả lại. Chỉ có một ____ 193, ví dụ của _nameToLevel = {
'CRITICAL': CRITICAL,
'FATAL': FATAL,
'ERROR': ERROR,
'WARN': WARNING,
'WARNING': WARNING,
'INFO': INFO,
'DEBUG': DEBUG,
'NOTSET': NOTSET,
}
def _checkLevel[level]:
if isinstance[level, int]:
rv = level
elif str[level] == level:
if level not in _nameToLevel:
raise ValueError["Unknown level: %r" % level]
rv = _nameToLevel[level]
else:
raise TypeError["Level not an integer or a valid string: %r" % level]
return rv
68 đã thảo luận ở trên.>>>
object
│
├── LogRecord
├── Filterer
│ ├── Logger
│ │ └── RootLogger
│ └── Handler
│ ├── StreamHandler
│ └── NullHandler
├── Filter
└── Manager
1object
│
├── LogRecord
├── Filterer
│ ├── Logger
│ │ └── RootLogger
│ └── Handler
│ ├── StreamHandler
│ └── NullHandler
├── Filter
└── Manager
12 thực sự làm gì?Thư viện vs đăng nhập ứng dụng: object
│
├── LogRecord
├── Filterer
│ ├── Logger
│ │ └── RootLogger
│ └── Handler
│ ├── StreamHandler
│ └── NullHandler
├── Filter
└── Manager
42 là gì?
object
│
├── LogRecord
├── Filterer
│ ├── Logger
│ │ └── RootLogger
│ └── Handler
│ ├── StreamHandler
│ └── NullHandler
├── Filter
└── Manager
Điều đó đưa chúng ta đến hàng trăm dòng cuối cùng trong nguồn
[Pdb] l
1514 exc_info = [type[exc_info], exc_info, exc_info.__traceback__]
1515 elif not isinstance[exc_info, tuple]:
1516 exc_info = sys.exc_info[]
1517 record = self.makeRecord[self.name, level, fn, lno, msg, args,
1518 exc_info, func, extra, sinfo]
1519 -> self.handle[record]
1520
1521 def handle[self, record]:
1522 """
1523 Call the handlers for the specified record.
1524
[Pdb] from pprint import pprint
[Pdb] pprint[vars[record]]
{'args': [],
'created': 1550671851.660067,
'exc_info': None,
'exc_text': None,
'filename': '',
'funcName': 'f',
'levelname': 'ERROR',
'levelno': 40,
'lineno': 2,
'module': '',
'msecs': 660.067081451416,
'msg': 'bad vibes',
'name': 'root',
'pathname': '',
'process': 2360,
'processName': 'MainProcess',
'relativeCreated': 295145.5490589142,
'stack_info': None,
'thread': 4372293056,
'threadName': 'MainThread'}
5, trong đó object
│
├── LogRecord
├── Filterer
│ ├── Logger
│ │ └── RootLogger
│ └── Handler
│ ├── StreamHandler
│ └── NullHandler
├── Filter
└── Manager
42 được xác định. Ở đây, định nghĩa trong tất cả vinh quang của nó:object
│
├── LogRecord
├── Filterer
│ ├── Logger
│ │ └── RootLogger
│ └── Handler
│ ├── StreamHandler
│ └── NullHandler
├── Filter
└── Manager
2object
│
├── LogRecord
├── Filterer
│ ├── Logger
│ │ └── RootLogger
│ └── Handler
│ ├── StreamHandler
│ └── NullHandler
├── Filter
└── Manager
42 là tất cả về sự khác biệt giữa việc đăng nhập vào thư viện so với một ứng dụng. Hãy để xem điều đó có nghĩa là gì.Một thư viện là một gói Python có thể tổng quát, có thể khái quát, dành cho người dùng khác để cài đặt và thiết lập. Nó được xây dựng bởi một nhà phát triển với mục đích rõ ràng là được phân phối cho người dùng. Các ví dụ bao gồm các dự án nguồn mở phổ biến như Numpy,
object
│
├── LogRecord
├── Filterer
│ ├── Logger
│ │ └── RootLogger
│ └── Handler
│ ├── StreamHandler
│ └── NullHandler
├── Filter
└── Manager
46 và object
│
├── LogRecord
├── Filterer
│ ├── Logger
│ │ └── RootLogger
│ └── Handler
│ ├── StreamHandler
│ └── NullHandler
├── Filter
└── Manager
47.library is an extensible, generalizable Python package that is intended for other users to install and set up. It is built by a developer with the express purpose of being distributed to users. Examples
include popular open-source projects like NumPy, object
│
├── LogRecord
├── Filterer
│ ├── Logger
│ │ └── RootLogger
│ └── Handler
│ ├── StreamHandler
│ └── NullHandler
├── Filter
└── Manager
46, and object
│
├── LogRecord
├── Filterer
│ ├── Logger
│ │ └── RootLogger
│ └── Handler
│ ├── StreamHandler
│ └── NullHandler
├── Filter
└── Manager
47.Một ứng dụng [hoặc ứng dụng hoặc chương trình] được thiết kế cho mục đích cụ thể hơn và một bộ người dùng nhỏ hơn nhiều [có thể chỉ là một người dùng]. Nó có một chương trình hoặc bộ chương trình được người dùng điều chỉnh cao để thực hiện một loạt mọi thứ. Một ví dụ về một ứng dụng là một ứng dụng Django nằm phía sau một trang web. Các ứng dụng thường sử dụng thư viện [
object
│
├── LogRecord
├── Filterer
│ ├── Logger
│ │ └── RootLogger
│ └── Handler
│ ├── StreamHandler
│ └── NullHandler
├── Filter
└── Manager
48] và các công cụ chúng chứa.application [or app, or program] is designed for a more specific purpose and a much smaller set of users [possibly just one user]. It’s a program or set of programs highly tailored by the user to do a
limited set of things. An example of an application is a Django app that sits behind a web page. Applications commonly use [object
│
├── LogRecord
├── Filterer
│ ├── Logger
│ │ └── RootLogger
│ └── Handler
│ ├── StreamHandler
│ └── NullHandler
├── Filter
└── Manager
48] libraries and the tools they contain.Khi nói đến việc ghi nhật ký, có các thực tiễn tốt nhất khác nhau trong thư viện so với một ứng dụng.
Đó là nơi mà
object
│
├── LogRecord
├── Filterer
│ ├── Logger
│ │ └── RootLogger
│ └── Handler
│ ├── StreamHandler
│ └── NullHandler
├── Filter
└── Manager
42 phù hợp. Nó về cơ bản là một lớp sở hữu không có gì.Nếu bạn đang viết một thư viện Python, bạn thực sự cần phải thực hiện một phần thiết lập tối giản này trong gói của bạn ____ ____ ____76:
object
│
├── LogRecord
├── Filterer
│ ├── Logger
│ │ └── RootLogger
│ └── Handler
│ ├── StreamHandler
│ └── NullHandler
├── Filter
└── Manager
3Điều này phục vụ hai mục đích quan trọng.
Đầu tiên, một bộ ghi thư viện được khai báo với
object
│
├── LogRecord
├── Filterer
│ ├── Logger
│ │ └── RootLogger
│ └── Handler
│ ├── StreamHandler
│ └── NullHandler
├── Filter
└── Manager
51 [không có bất kỳ cấu hình nào khác] sẽ đăng nhập vào CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
35 theo mặc định, ngay cả khi đó không phải là những gì người dùng cuối muốn. Điều này có thể được mô tả như là một cách tiếp cận từ chối, trong đó người dùng cuối của thư viện phải đi vào và vô hiệu hóa việc đăng nhập vào bảng điều khiển của họ nếu họ không muốn nó.Thay vào đó, trí tuệ thông thường cho biết sử dụng cách tiếp cận chọn tham gia thay thế: don lồng phát ra bất kỳ thông báo nhật ký nào theo mặc định và để người dùng cuối của thư viện xác định xem họ có muốn định cấu hình thêm trình ghi nhật ký thư viện và thêm người xử lý cho họ không. Ở đây, triết lý mà tác giả của gói
import logging
import sys
logger = logging.getLogger["pylog"]
logger.setLevel[logging.DEBUG]
h2 = logging.FileHandler[filename="/tmp/records.log"]
h2.setLevel[logging.INFO]
h2 = logging.StreamHandler[sys.stderr]
h2.setLevel[logging.ERROR]
logger.addHandler[h2]
logger.addHandler[h2]
logger.info["testing %d.. %d.. %d..", 1, 2, 3]
5, Vinay Sajip: Vinay Sajip:Thư viện của bên thứ ba sử dụng
5 không nên phun ra đầu ra ghi nhật ký theo mặc định mà không thể mong muốn bởi nhà phát triển/người dùng ứng dụng sử dụng nó. [Nguồn]import logging import sys logger = logging.getLogger["pylog"] logger.setLevel[logging.DEBUG] h2 = logging.FileHandler[filename="/tmp/records.log"] h2.setLevel[logging.INFO] h2 = logging.StreamHandler[sys.stderr] h2.setLevel[logging.ERROR] logger.addHandler[h2] logger.addHandler[h2] logger.info["testing %d.. %d.. %d..", 1, 2, 3]
Điều này để lại cho người dùng thư viện, không phải nhà phát triển thư viện, để gọi các phương thức tăng dần như
object
│
├── LogRecord
├── Filterer
│ ├── Logger
│ │ └── RootLogger
│ └── Handler
│ ├── StreamHandler
│ └── NullHandler
├── Filter
└── Manager
55 hoặc object
│
├── LogRecord
├── Filterer
│ ├── Logger
│ │ └── RootLogger
│ └── Handler
│ ├── StreamHandler
│ └── NullHandler
├── Filter
└── Manager
56.Lý do thứ hai mà
object
│
├── LogRecord
├── Filterer
│ ├── Logger
│ │ └── RootLogger
│ └── Handler
│ ├── StreamHandler
│ └── NullHandler
├── Filter
└── Manager
42 tồn tại là cổ xưa hơn. Trong Python 2.7 và trước đó, cố gắng đăng nhập CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
29 từ một logger không có bộ xử lý sẽ đưa ra cảnh báo. Thêm lớp NO-OP object
│
├── LogRecord
├── Filterer
│ ├── Logger
│ │ └── RootLogger
│ └── Handler
│ ├── StreamHandler
│ └── NullHandler
├── Filter
└── Manager
42 sẽ ngăn chặn điều này.Tại đây, những gì đặc biệt xảy ra trong dòng
object
│
├── LogRecord
├── Filterer
│ ├── Logger
│ │ └── RootLogger
│ └── Handler
│ ├── StreamHandler
│ └── NullHandler
├── Filter
└── Manager
60 từ trên:Python được [tạo] phiên bản
12 có cùng tên với gói của bạn. Nếu bạn đang thiết kế góiCRITICAL = 50 FATAL = CRITICAL ERROR = 40 WARNING = 30 WARN = WARNING INFO = 20 DEBUG = 10 NOTSET = 0
62, trong vòngobject │ ├── LogRecord ├── Filterer │ ├── Logger │ │ └── RootLogger │ └── Handler │ ├── StreamHandler │ └── NullHandler ├── Filter └── Manager
6, thì[Pdb] l 1514 exc_info = [type[exc_info], exc_info, exc_info.__traceback__] 1515 elif not isinstance[exc_info, tuple]: 1516 exc_info = sys.exc_info[] 1517 record = self.makeRecord[self.name, level, fn, lno, msg, args, 1518 exc_info, func, extra, sinfo] 1519 -> self.handle[record] 1520 1521 def handle[self, record]: 1522 """ 1523 Call the handlers for the specified record. 1524 [Pdb] from pprint import pprint [Pdb] pprint[vars[record]] {'args': [], 'created': 1550671851.660067, 'exc_info': None, 'exc_text': None, 'filename': '', 'funcName': 'f', 'levelname': 'ERROR', 'levelno': 40, 'lineno': 2, 'module': '', 'msecs': 660.067081451416, 'msg': 'bad vibes', 'name': 'root', 'pathname': '', 'process': 2360, 'processName': 'MainProcess', 'relativeCreated': 295145.5490589142, 'stack_info': None, 'thread': 4372293056, 'threadName': 'MainThread'}
12 sẽ bằngimport threading _lock = threading.RLock[] def _acquireLock[]: if _lock: _lock.acquire[] def _releaseLock[]: if _lock: _lock.release[]
65.object │ ├── LogRecord ├── Filterer │ ├── Logger │ │ └── RootLogger │ └── Handler │ ├── StreamHandler │ └── NullHandler ├── Filter └── Manager
Một ví dụ
42 được gắn vào logger này. Điều đó có nghĩa là Python sẽ không mặc định sử dụng trình xử lýobject │ ├── LogRecord ├── Filterer │ ├── Logger │ │ └── RootLogger │ └── Handler │ ├── StreamHandler │ └── NullHandler ├── Filter └── Manager
49.import threading _lock = threading.RLock[] def _acquireLock[]: if _lock: _lock.acquire[] def _releaseLock[]: if _lock: _lock.release[]
Hãy nhớ rằng bất kỳ logger nào được tạo trong bất kỳ mô -đun
object
│
├── LogRecord
├── Filterer
│ ├── Logger
│ │ └── RootLogger
│ └── Handler
│ ├── StreamHandler
│ └── NullHandler
├── Filter
└── Manager
68 nào khác của gói sẽ là trẻ em của bộ ghi này trong hệ thống phân cấp logger và vì người xử lý này cũng thuộc về chúng, họ sẽ không cần sử dụng trình xử lý import threading
_lock = threading.RLock[]
def _acquireLock[]:
if _lock:
_lock.acquire[]
def _releaseLock[]:
if _lock:
_lock.release[]
49 và giành được 'T mặc định để đăng nhập vào lỗi tiêu chuẩn [CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
39].Ví dụ nhanh, hãy để nói rằng thư viện của bạn có cấu trúc sau:
object
│
├── LogRecord
├── Filterer
│ ├── Logger
│ │ └── RootLogger
│ └── Handler
│ ├── StreamHandler
│ └── NullHandler
├── Filter
└── Manager
4Trong
object
│
├── LogRecord
├── Filterer
│ ├── Logger
│ │ └── RootLogger
│ └── Handler
│ ├── StreamHandler
│ └── NullHandler
├── Filter
└── Manager
71, với tư cách là nhà phát triển thư viện, bạn có thể tự do thực hiện như sau:object
│
├── LogRecord
├── Filterer
│ ├── Logger
│ │ └── RootLogger
│ └── Handler
│ ├── StreamHandler
│ └── NullHandler
├── Filter
└── Manager
5Bây giờ, người dùng xuất hiện và cài đặt thư viện của bạn từ PYPI thông qua
object
│
├── LogRecord
├── Filterer
│ ├── Logger
│ │ └── RootLogger
│ └── Handler
│ ├── StreamHandler
│ └── NullHandler
├── Filter
└── Manager
72. Họ sử dụng object
│
├── LogRecord
├── Filterer
│ ├── Logger
│ │ └── RootLogger
│ └── Handler
│ ├── StreamHandler
│ └── NullHandler
├── Filter
└── Manager
73 trong một số mã ứng dụng. Người dùng này có thể tự do thao tác và định cấu hình đối tượng CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
16 từ thư viện như bất kỳ đối tượng Python nào khác, đến nội dung trái tim của họ.Ghi nhật ký làm gì với ngoại lệ
Một điều mà bạn có thể cảnh giác là nguy cơ ngoại lệ xuất phát từ các cuộc gọi của bạn đến
import logging
import sys
logger = logging.getLogger["pylog"]
logger.setLevel[logging.DEBUG]
h2 = logging.FileHandler[filename="/tmp/records.log"]
h2.setLevel[logging.INFO]
h2 = logging.StreamHandler[sys.stderr]
h2.setLevel[logging.ERROR]
logger.addHandler[h2]
logger.addHandler[h2]
logger.info["testing %d.. %d.. %d..", 1, 2, 3]
5. Nếu bạn có một cuộc gọi CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
51 được thiết kế để cung cấp cho bạn một số thông tin gỡ lỗi dài dòng hơn, nhưng đó là một số lý do sẽ làm tăng một ngoại lệ, đó sẽ là chiều cao của sự trớ trêu, phải không?Thông minh, nếu gói
import logging
import sys
logger = logging.getLogger["pylog"]
logger.setLevel[logging.DEBUG]
h2 = logging.FileHandler[filename="/tmp/records.log"]
h2.setLevel[logging.INFO]
h2 = logging.StreamHandler[sys.stderr]
h2.setLevel[logging.ERROR]
logger.addHandler[h2]
logger.addHandler[h2]
logger.info["testing %d.. %d.. %d..", 1, 2, 3]
5 gặp phải một ngoại lệ có liên quan đến việc ghi lại, thì nó sẽ in dấu vết nhưng không tự tăng ngoại lệ.Ở đây, một ví dụ liên quan đến một lỗi đánh máy phổ biến: chuyển hai đối số cho một chuỗi định dạng chỉ mong đợi một đối số. Sự khác biệt quan trọng là những gì bạn thấy dưới đây không phải là một ngoại lệ được nêu ra, mà là một dấu vết in được in của ngoại lệ nội bộ, mà chính nó đã bị đàn áp:
>>>
object
│
├── LogRecord
├── Filterer
│ ├── Logger
│ │ └── RootLogger
│ └── Handler
│ ├── StreamHandler
│ └── NullHandler
├── Filter
└── Manager
6Điều này cho phép chương trình của bạn duyên dáng tiếp tục với luồng chương trình thực tế của nó. Lý do là bạn sẽ không muốn một ngoại lệ không được nhận ra từ một cuộc gọi
import logging
import sys
logger = logging.getLogger["pylog"]
logger.setLevel[logging.DEBUG]
h2 = logging.FileHandler[filename="/tmp/records.log"]
h2.setLevel[logging.INFO]
h2 = logging.StreamHandler[sys.stderr]
h2.setLevel[logging.ERROR]
logger.addHandler[h2]
logger.addHandler[h2]
logger.info["testing %d.. %d.. %d..", 1, 2, 3]
5 và ngăn chặn một chương trình chết trong các bài hát của nó.Tracebacks có thể lộn xộn, nhưng cái này là thông tin và tương đối đơn giản. Điều cho phép đàn áp các ngoại lệ liên quan đến
import logging
import sys
logger = logging.getLogger["pylog"]
logger.setLevel[logging.DEBUG]
h2 = logging.FileHandler[filename="/tmp/records.log"]
h2.setLevel[logging.INFO]
h2 = logging.StreamHandler[sys.stderr]
h2.setLevel[logging.ERROR]
logger.addHandler[h2]
logger.addHandler[h2]
logger.info["testing %d.. %d.. %d..", 1, 2, 3]
5 là object
│
├── LogRecord
├── Filterer
│ ├── Logger
│ │ └── RootLogger
│ └── Handler
│ ├── StreamHandler
│ └── NullHandler
├── Filter
└── Manager
80. Khi người xử lý gọi CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
41, đó là phương pháp mà nó cố gắng ghi lại bản ghi, nó sẽ trở lại object
│
├── LogRecord
├── Filterer
│ ├── Logger
│ │ └── RootLogger
│ └── Handler
│ ├── StreamHandler
│ └── NullHandler
├── Filter
└── Manager
82 nếu có điều gì đó tồi tệ. Tại đây, việc triển khai CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
41 cho lớp import threading
_lock = threading.RLock[]
def _acquireLock[]:
if _lock:
_lock.acquire[]
def _releaseLock[]:
if _lock:
_lock.release[]
56:
object
│
├── LogRecord
├── Filterer
│ ├── Logger
│ │ └── RootLogger
│ └── Handler
│ ├── StreamHandler
│ └── NullHandler
├── Filter
└── Manager
7Bất kỳ ngoại lệ nào liên quan đến định dạng và văn bản đều bị bắt thay vì được nuôi dưỡng, và
object
│
├── LogRecord
├── Filterer
│ ├── Logger
│ │ └── RootLogger
│ └── Handler
│ ├── StreamHandler
│ └── NullHandler
├── Filter
└── Manager
85 duyên dáng viết dấu vết lên CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
35.Ghi nhật ký Python Tracebacks
Nói về các trường hợp ngoại lệ và dấu vết của họ, những trường hợp chương trình của bạn gặp họ nhưng nên đăng nhập ngoại lệ và tiếp tục theo dõi trong việc thực hiện của nó?
Hãy cùng đi qua một vài cách để làm điều này.
Ở đây, một ví dụ giả định về một trình mô phỏng xổ số bằng cách sử dụng mã không có mục đích. Bạn đang phát triển một trò chơi xổ số trực tuyến, nơi người dùng có thể đặt cược vào số may mắn của họ:
object
│
├── LogRecord
├── Filterer
│ ├── Logger
│ │ └── RootLogger
│ └── Handler
│ ├── StreamHandler
│ └── NullHandler
├── Filter
└── Manager
8Đằng sau ứng dụng Frontend nằm trong mã quan trọng dưới đây. Bạn muốn đảm bảo rằng bạn theo dõi bất kỳ lỗi nào do trang web có thể khiến người dùng mất tiền. Cách đầu tiên [tối ưu] là sử dụng
CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
51 và đăng nhập hình thức class Logger[Filterer]:
# ...
def getEffectiveLevel[self]:
logger = self
while logger:
if logger.level:
return logger.level
logger = logger.parent
return NOTSET
def isEnabledFor[self, level]:
try:
return self._cache[level]
except KeyError:
_acquireLock[]
if self.manager.disable >= level:
is_enabled = self._cache[level] = False
else:
is_enabled = self._cache[level] = level >= self.getEffectiveLevel[]
_releaseLock[]
return is_enabled
5 của trường hợp ngoại lệ:object
│
├── LogRecord
├── Filterer
│ ├── Logger
│ │ └── RootLogger
│ └── Handler
│ ├── StreamHandler
│ └── NullHandler
├── Filter
└── Manager
9Điều này sẽ chỉ nhận được thông báo ngoại lệ thực tế, thay vì truy tìm. Bạn kiểm tra nhật ký trên máy chủ trang web của bạn và tìm tin nhắn khó hiểu này:
import logging
import sys
logger = logging.getLogger["pylog"]
logger.setLevel[logging.DEBUG]
h2 = logging.FileHandler[filename="/tmp/records.log"]
h2.setLevel[logging.INFO]
h2 = logging.StreamHandler[sys.stderr]
h2.setLevel[logging.ERROR]
logger.addHandler[h2]
logger.addHandler[h2]
logger.info["testing %d.. %d.. %d..", 1, 2, 3]
0Hmm. Là nhà phát triển ứng dụng, bạn đã gặp vấn đề nghiêm trọng và kết quả là người dùng đã bị gạt ra. Nhưng có lẽ thông điệp ngoại lệ này là rất nhiều thông tin. Sẽ rất vui khi thấy dòng dõi của dấu vết dẫn đến ngoại lệ này?
Giải pháp thích hợp là sử dụng
object
│
├── LogRecord
├── Filterer
│ ├── Logger
│ │ └── RootLogger
│ └── Handler
│ ├── StreamHandler
│ └── NullHandler
├── Filter
└── Manager
89, ghi lại một thông điệp với cấp CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
36 và cũng hiển thị truy tìm ngoại lệ. Thay thế hai dòng cuối cùng ở trên bằng những điều này:import logging
import sys
logger = logging.getLogger["pylog"]
logger.setLevel[logging.DEBUG]
h2 = logging.FileHandler[filename="/tmp/records.log"]
h2.setLevel[logging.INFO]
h2 = logging.StreamHandler[sys.stderr]
h2.setLevel[logging.ERROR]
logger.addHandler[h2]
logger.addHandler[h2]
logger.info["testing %d.. %d.. %d..", 1, 2, 3]
1Bây giờ bạn nhận được một dấu hiệu tốt hơn về những gì đang diễn ra:
>>>
import logging
import sys
logger = logging.getLogger["pylog"]
logger.setLevel[logging.DEBUG]
h2 = logging.FileHandler[filename="/tmp/records.log"]
h2.setLevel[logging.INFO]
h2 = logging.StreamHandler[sys.stderr]
h2.setLevel[logging.ERROR]
logger.addHandler[h2]
logger.addHandler[h2]
logger.info["testing %d.. %d.. %d..", 1, 2, 3]
2Sử dụng
object
│
├── LogRecord
├── Filterer
│ ├── Logger
│ │ └── RootLogger
│ └── Handler
│ ├── StreamHandler
│ └── NullHandler
├── Filter
└── Manager
91 giúp bạn không phải tự tham khảo ngoại lệ vì import logging
import sys
logger = logging.getLogger["pylog"]
logger.setLevel[logging.DEBUG]
h2 = logging.FileHandler[filename="/tmp/records.log"]
h2.setLevel[logging.INFO]
h2 = logging.StreamHandler[sys.stderr]
h2.setLevel[logging.ERROR]
logger.addHandler[h2]
logger.addHandler[h2]
logger.info["testing %d.. %d.. %d..", 1, 2, 3]
5 kéo nó vào với object
│
├── LogRecord
├── Filterer
│ ├── Logger
│ │ └── RootLogger
│ └── Handler
│ ├── StreamHandler
│ └── NullHandler
├── Filter
└── Manager
93.Điều này làm cho mọi thứ rõ ràng hơn rằng vấn đề bắt nguồn từ
object
│
├── LogRecord
├── Filterer
│ ├── Logger
│ │ └── RootLogger
│ └── Handler
│ ├── StreamHandler
│ └── NullHandler
├── Filter
└── Manager
94, cần biết độ dài của đối tượng mà nó đang xáo trộn. Bởi vì lớp object
│
├── LogRecord
├── Filterer
│ ├── Logger
│ │ └── RootLogger
│ └── Handler
│ ├── StreamHandler
│ └── NullHandler
├── Filter
└── Manager
95 của chúng tôi chuyển một máy phát điện đến object
│
├── LogRecord
├── Filterer
│ ├── Logger
│ │ └── RootLogger
│ └── Handler
│ ├── StreamHandler
│ └── NullHandler
├── Filter
└── Manager
96, nó sẽ được giữ và tăng trước khi hồ bơi có thể bị xáo trộn, ít tạo ra một vé chiến thắng.Trong các ứng dụng lớn, toàn diện, bạn sẽ thấy
object
│
├── LogRecord
├── Filterer
│ ├── Logger
│ │ └── RootLogger
│ └── Handler
│ ├── StreamHandler
│ └── NullHandler
├── Filter
└── Manager
89 thậm chí còn hữu ích hơn khi các dấu vết đa thư viện sâu thẳm có liên quan và bạn có thể bước vào chúng với một trình gỡ lỗi trực tiếp như CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
52.Mã cho
object
│
├── LogRecord
├── Filterer
│ ├── Logger
│ │ └── RootLogger
│ └── Handler
│ ├── StreamHandler
│ └── NullHandler
├── Filter
└── Manager
99, và do đó object
│
├── LogRecord
├── Filterer
│ ├── Logger
│ │ └── RootLogger
│ └── Handler
│ ├── StreamHandler
│ └── NullHandler
├── Filter
└── Manager
89, chỉ là một dòng duy nhất:import logging
import sys
logger = logging.getLogger["pylog"]
logger.setLevel[logging.DEBUG]
h2 = logging.FileHandler[filename="/tmp/records.log"]
h2.setLevel[logging.INFO]
h2 = logging.StreamHandler[sys.stderr]
h2.setLevel[logging.ERROR]
logger.addHandler[h2]
logger.addHandler[h2]
logger.info["testing %d.. %d.. %d..", 1, 2, 3]
3Nghĩa là,
object
│
├── LogRecord
├── Filterer
│ ├── Logger
│ │ └── RootLogger
│ └── Handler
│ ├── StreamHandler
│ └── NullHandler
├── Filter
└── Manager
89 chỉ gọi CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
51 với import logging
import sys
logger = logging.getLogger["pylog"]
logger.setLevel[logging.DEBUG]
h2 = logging.FileHandler[filename="/tmp/records.log"]
h2.setLevel[logging.INFO]
h2 = logging.StreamHandler[sys.stderr]
h2.setLevel[logging.ERROR]
logger.addHandler[h2]
logger.addHandler[h2]
logger.info["testing %d.. %d.. %d..", 1, 2, 3]
03, nếu không thì _nameToLevel = {
'CRITICAL': CRITICAL,
'FATAL': FATAL,
'ERROR': ERROR,
'WARN': WARNING,
'WARNING': WARNING,
'INFO': INFO,
'DEBUG': DEBUG,
'NOTSET': NOTSET,
}
def _checkLevel[level]:
if isinstance[level, int]:
rv = level
elif str[level] == level:
if level not in _nameToLevel:
raise ValueError["Unknown level: %r" % level]
rv = _nameToLevel[level]
else:
raise TypeError["Level not an integer or a valid string: %r" % level]
return rv
48 theo mặc định. Nếu bạn muốn đăng nhập một dấu vết ngoại lệ nhưng ở cấp độ khác với import logging
import sys
logger = logging.getLogger["pylog"]
logger.setLevel[logging.DEBUG]
h2 = logging.FileHandler[filename="/tmp/records.log"]
h2.setLevel[logging.INFO]
h2 = logging.StreamHandler[sys.stderr]
h2.setLevel[logging.ERROR]
logger.addHandler[h2]
logger.addHandler[h2]
logger.info["testing %d.. %d.. %d..", 1, 2, 3]
05, chỉ cần gọi hàm đó hoặc phương thức với import logging
import sys
logger = logging.getLogger["pylog"]
logger.setLevel[logging.DEBUG]
h2 = logging.FileHandler[filename="/tmp/records.log"]
h2.setLevel[logging.INFO]
h2 = logging.StreamHandler[sys.stderr]
h2.setLevel[logging.ERROR]
logger.addHandler[h2]
logger.addHandler[h2]
logger.info["testing %d.. %d.. %d..", 1, 2, 3]
03.Hãy nhớ rằng
object
│
├── LogRecord
├── Filterer
│ ├── Logger
│ │ └── RootLogger
│ └── Handler
│ ├── StreamHandler
│ └── NullHandler
├── Filter
└── Manager
91 chỉ nên được gọi trong bối cảnh của một trình xử lý ngoại lệ, bên trong một khối import logging
import sys
logger = logging.getLogger["pylog"]
logger.setLevel[logging.DEBUG]
h2 = logging.FileHandler[filename="/tmp/records.log"]
h2.setLevel[logging.INFO]
h2 = logging.StreamHandler[sys.stderr]
h2.setLevel[logging.ERROR]
logger.addHandler[h2]
logger.addHandler[h2]
logger.info["testing %d.. %d.. %d..", 1, 2, 3]
08:import logging
import sys
logger = logging.getLogger["pylog"]
logger.setLevel[logging.DEBUG]
h2 = logging.FileHandler[filename="/tmp/records.log"]
h2.setLevel[logging.INFO]
h2 = logging.StreamHandler[sys.stderr]
h2.setLevel[logging.ERROR]
logger.addHandler[h2]
logger.addHandler[h2]
logger.info["testing %d.. %d.. %d..", 1, 2, 3]
4Sử dụng mẫu này một cách tiết kiệm hơn là một phương tiện để đàn áp bất kỳ ngoại lệ nào. Nó có thể hữu ích nhất khi bạn gỡ lỗi một ngăn xếp gọi chức năng dài nơi bạn có thể thấy một lỗi mơ hồ, không rõ ràng và khó theo dõi.
Sự kết luận
Hãy vỗ nhẹ vào lưng, bởi vì bạn đã đi qua gần 2.000 dòng mã nguồn dày đặc. Bạn bây giờ được trang bị tốt hơn để đối phó với gói
import logging
import sys
logger = logging.getLogger["pylog"]
logger.setLevel[logging.DEBUG]
h2 = logging.FileHandler[filename="/tmp/records.log"]
h2.setLevel[logging.INFO]
h2 = logging.StreamHandler[sys.stderr]
h2.setLevel[logging.ERROR]
logger.addHandler[h2]
logger.addHandler[h2]
logger.info["testing %d.. %d.. %d..", 1, 2, 3]
5!Hãy nhớ rằng hướng dẫn này đã không còn toàn bộ trong việc bao gồm tất cả các lớp học được tìm thấy trong gói
import logging
import sys
logger = logging.getLogger["pylog"]
logger.setLevel[logging.DEBUG]
h2 = logging.FileHandler[filename="/tmp/records.log"]
h2.setLevel[logging.INFO]
h2 = logging.StreamHandler[sys.stderr]
h2.setLevel[logging.ERROR]
logger.addHandler[h2]
logger.addHandler[h2]
logger.info["testing %d.. %d.. %d..", 1, 2, 3]
5. Có nhiều máy móc thậm chí còn gắn kết mọi thứ lại với nhau. Nếu bạn muốn tìm hiểu thêm, thì bạn có thể xem xét các lớp import logging
import sys
logger = logging.getLogger["pylog"]
logger.setLevel[logging.DEBUG]
h2 = logging.FileHandler[filename="/tmp/records.log"]
h2.setLevel[logging.INFO]
h2 = logging.StreamHandler[sys.stderr]
h2.setLevel[logging.ERROR]
logger.addHandler[h2]
logger.addHandler[h2]
logger.info["testing %d.. %d.. %d..", 1, 2, 3]
11 và các mô -đun riêng biệt import logging
import sys
logger = logging.getLogger["pylog"]
logger.setLevel[logging.DEBUG]
h2 = logging.FileHandler[filename="/tmp/records.log"]
h2.setLevel[logging.INFO]
h2 = logging.StreamHandler[sys.stderr]
h2.setLevel[logging.ERROR]
logger.addHandler[h2]
logger.addHandler[h2]
logger.info["testing %d.. %d.. %d..", 1, 2, 3]
12 và import logging
import sys
logger = logging.getLogger["pylog"]
logger.setLevel[logging.DEBUG]
h2 = logging.FileHandler[filename="/tmp/records.log"]
h2.setLevel[logging.INFO]
h2 = logging.StreamHandler[sys.stderr]
h2.setLevel[logging.ERROR]
logger.addHandler[h2]
logger.addHandler[h2]
logger.info["testing %d.. %d.. %d..", 1, 2, 3]
13.