logging.config
— 日誌配置¶
本節介紹用於配置日誌模組的 API。
配置函式¶
以下函式配置日誌模組。它們位於 logging.config
模組中。它們的使用是可選的——你可以使用這些函式或呼叫主 API(在 logging
本身中定義)並定義在 logging
或 logging.handlers
中宣告的處理器來配置日誌模組。
- logging.config.dictConfig(config)¶
從字典中獲取日誌配置。此字典的內容在下面的 配置字典模式 中描述。
如果在配置過程中遇到錯誤,此函式將引發
ValueError
、TypeError
、AttributeError
或ImportError
,並附帶適當的描述性訊息。以下是(可能不完整)的將引發錯誤的情況列表:level
不是字串,或者是一個不對應於實際日誌級別的字串。propagate
值不是布林值。id 沒有對應的目標。
在增量呼叫期間找到不存在的處理器 id。
無效的日誌記錄器名稱。
無法解析為內部或外部物件。
解析由
DictConfigurator
類執行,該類的建構函式傳遞用於配置的字典,並具有一個configure()
方法。logging.config
模組具有一個可呼叫屬性dictConfigClass
,該屬性最初設定為DictConfigurator
。你可以用你自己的合適實現替換dictConfigClass
的值。dictConfig()
呼叫dictConfigClass
並傳遞指定的字典,然後呼叫返回物件上的configure()
方法使配置生效def dictConfig(config): dictConfigClass(config).configure()
例如,
DictConfigurator
的子類可以在其自身的__init__()
中呼叫DictConfigurator.__init__()
,然後設定自定義字首,這些字首可在後續的configure()
呼叫中使用。dictConfigClass
將繫結到這個新的子類,然後可以像預設的、未定製的狀態下那樣呼叫dictConfig()
。3.2 版本新增。
- logging.config.fileConfig(fname, defaults=None, disable_existing_loggers=True, encoding=None)¶
從
configparser
格式的檔案中讀取日誌配置。檔案的格式應如 配置檔案格式 中所述。可以從應用程式多次呼叫此函式,允許終端使用者從各種預先準備好的配置中進行選擇(如果開發人員提供了一種機制來呈現選擇並載入所選配置)。如果檔案不存在,將引發
FileNotFoundError
,如果檔案無效或為空,則引發RuntimeError
。- 引數:
fname – 一個檔名、一個類似檔案的物件或一個派生自
RawConfigParser
的例項。如果傳遞了RawConfigParser
派生的例項,則按原樣使用。否則,將例項化一個ConfigParser
,並由它從fname
中傳遞的物件讀取配置。如果它有一個readline()
方法,則假定它是一個類似檔案的物件,並使用read_file()
讀取;否則,假定它是一個檔名並傳遞給read()
。defaults – 可以在此引數中指定要傳遞給
ConfigParser
的預設值。disable_existing_loggers – 如果指定為
False
,則在呼叫此函式時存在的日誌記錄器保持啟用狀態。預設值為True
,因為這以向後相容的方式啟用了舊的行為。此行為是停用任何現有的非根日誌記錄器,除非它們或它們的祖先在日誌配置中被明確命名。encoding – 當 fname 是檔名時,用於開啟檔案的編碼。
在 3.4 版本中更改:現在接受
RawConfigParser
子類的例項作為fname
的值。這有助於使用配置檔案,其中日誌配置只是整個應用程式配置的一部分。
使用從檔案中讀取的配置,然後由使用應用程式進行修改(例如,基於命令列引數或執行時環境的其他方面),然後再傳遞給
fileConfig
。
在 3.10 版本中變更: 添加了 encoding 引數。
在 3.12 版本中變更: 如果提供的檔案不存在、無效或為空,則會引發異常。
- logging.config.listen(port=DEFAULT_LOGGING_CONFIG_PORT, verify=None)¶
在指定的埠上啟動一個套接字伺服器,並監聽新的配置。如果未指定埠,則使用模組的預設
DEFAULT_LOGGING_CONFIG_PORT
。日誌配置將作為適合由dictConfig()
或fileConfig()
處理的檔案傳送。返回一個Thread
例項,您可以在該例項上呼叫start()
來啟動伺服器,並在適當的時候呼叫join()
。要停止伺服器,請呼叫stopListening()
。如果指定了
verify
引數,則它應該是一個可呼叫物件,用於驗證透過套接字接收的位元組是否有效並應該處理。這可以透過加密和/或簽名透過套接字傳送的內容來完成,以便verify
可呼叫物件可以執行簽名驗證和/或解密。verify
可呼叫物件使用單個引數(透過套接字接收的位元組)呼叫,並且應返回要處理的位元組,或者返回None
以指示應丟棄該位元組。返回的位元組可以與傳入的位元組相同(例如,當僅進行驗證時),或者它們可能完全不同(可能在執行解密的情況下)。要將配置傳送到套接字,請讀取配置檔案並將其作為位元組序列傳送到套接字,該位元組序列以使用
struct.pack('>L', n)
以二進位制形式打包的四位元組長度字串為字首。注意
由於配置的某些部分是透過
eval()
傳遞的,因此使用此函式可能會使使用者面臨安全風險。儘管該函式僅繫結到localhost
上的套接字,因此不接受來自遠端計算機的連線,但在某些情況下,不受信任的程式碼可能會在呼叫listen()
的程序的帳戶下執行。具體而言,如果呼叫listen()
的程序在使用者之間不能相互信任的多使用者計算機上執行,則惡意使用者可以透過簡單地連線到受害者的listen()
套接字併發送一個配置來執行攻擊者想要在受害者程序中執行的任何程式碼,從而安排在受害者使用者的程序中執行本質上是任意的程式碼。如果使用預設埠,則尤其容易做到這一點,但是即使使用不同的埠也不難。為了避免這種情況發生的風險,請使用listen()
的verify
引數來防止應用無法識別的配置。在 3.4 版本中變更: 添加了
verify
引數。注意
如果您想將配置傳送到監聽器,而不會停用現有的記錄器,則需要使用 JSON 格式進行配置,這將使用
dictConfig()
進行配置。此方法允許您在傳送的配置中將disable_existing_loggers
指定為False
。
安全注意事項¶
日誌配置功能試圖提供便利,部分是透過提供將配置檔案中的文字轉換為日誌配置中使用的 Python 物件的能力來實現的 - 例如,如 使用者定義的物件 中所述。但是,這些相同的機制(從使用者定義的模組匯入可呼叫物件並使用配置中的引數呼叫它們)可用於呼叫您喜歡的任何程式碼,因此您應該極其謹慎地對待來自不受信任來源的配置檔案,並在實際載入它們之前,確保載入它們不會發生任何不好的事情。
配置字典架構¶
描述日誌配置需要列出要建立的各種物件以及它們之間的連線;例如,您可以建立一個名為“console”的處理程式,然後說名為“startup”的記錄器會將其訊息傳送到“console”處理程式。這些物件不僅限於 logging
模組提供的物件,因為您可以編寫自己的格式化程式或處理程式類。這些類的引數可能還需要包含外部物件,例如 sys.stderr
。用於描述這些物件和連線的語法在下面的 物件連線 中定義。
字典架構詳細資訊¶
傳遞給 dictConfig()
的字典必須包含以下鍵
version - 設定為表示架構版本的整數值。目前唯一有效的值是 1,但是擁有此鍵可以使架構在保持向後相容性的同時進行演變。
所有其他鍵都是可選的,但如果存在,它們將被解釋如下所述。在下面所有提到“配置字典”的情況下,都將檢查特殊的 '()'
鍵,以檢視是否需要自定義例項化。如果是,則使用下面 使用者定義的物件 中描述的機制來建立例項;否則,將使用上下文來確定要例項化的內容。
formatters - 對應的值將是一個字典,其中每個鍵都是一個格式化程式 ID,每個值都是一個描述如何配置對應的
Formatter
例項的字典。在配置字典中搜索以下可選鍵,這些鍵與傳遞給建立
Formatter
物件的引數相對應format
datefmt
style
validate
(自版本 >=3.8)defaults
(自版本 >=3.12)
一個可選的
class
鍵表示格式化器的類名(使用點分隔的模組和類名)。例項化引數與Formatter
的相同,因此此鍵最適用於例項化Formatter
的自定義子類。例如,替代類可能以展開或壓縮的格式呈現異常回溯。如果你的格式化器需要不同的或額外的配置鍵,你應該使用 使用者定義的物件。filters - 對應的值將是一個字典,其中每個鍵是一個過濾器 ID,每個值是一個描述如何配置相應過濾器例項的字典。
配置字典會搜尋鍵
name
(預設為空字串),並用它來構造一個logging.Filter
例項。handlers - 對應的值將是一個字典,其中每個鍵是一個處理器 ID,每個值是一個描述如何配置相應處理器例項的字典。
配置字典會搜尋以下鍵:
class
(必選)。這是處理器類的完整限定名稱。level
(可選)。處理器的級別。formatter
(可選)。此處理器的格式化器 ID。filters
(可選)。此處理器的過濾器 ID 列表。在 3.11 版本中更改:
filters
除了 ID 之外,還可以接受過濾器例項。
所有其他鍵都作為關鍵字引數傳遞給處理器的建構函式。例如,給定以下程式碼片段:
handlers: console: class : logging.StreamHandler formatter: brief level : INFO filters: [allow_foo] stream : ext://sys.stdout file: class : logging.handlers.RotatingFileHandler formatter: precise filename: logconfig.log maxBytes: 1024 backupCount: 3
ID 為
console
的處理器被例項化為logging.StreamHandler
,使用sys.stdout
作為底層流。ID 為file
的處理器被例項化為logging.handlers.RotatingFileHandler
,並帶有關鍵字引數filename='logconfig.log', maxBytes=1024, backupCount=3
。loggers - 對應的值將是一個字典,其中每個鍵是一個記錄器名稱,每個值是一個描述如何配置相應記錄器例項的字典。
配置字典會搜尋以下鍵:
level
(可選)。記錄器的級別。propagate
(可選)。記錄器的傳播設定。filters
(可選)。此記錄器的過濾器 ID 列表。在 3.11 版本中更改:
filters
除了 ID 之外,還可以接受過濾器例項。handlers
(可選)。此記錄器的處理器 ID 列表。
指定的記錄器將根據指定的級別、傳播、過濾器和處理器進行配置。
root - 這將是根記錄器的配置。配置的處理方式與任何記錄器相同,只是
propagate
設定不適用。incremental - 是否將配置解釋為對現有配置的增量。此值預設為
False
,這意味著指定的配置將替換現有配置,其語義與現有fileConfig()
API 使用的相同。如果指定的值為
True
,則按照 增量配置 部分中的描述處理配置。disable_existing_loggers - 是否停用任何現有的非根記錄器。此設定與
fileConfig()
中同名的引數相呼應。如果不存在,則此引數預設為True
。如果 incremental 為True
,則忽略此值。
增量配置¶
為增量配置提供完全的靈活性是很困難的。例如,由於過濾器和格式化器等物件是匿名的,因此一旦設定了配置,就不可能在增強配置時引用這些匿名物件。
此外,一旦設定了配置,就沒有充分的理由在執行時任意更改記錄器、處理器、過濾器和格式化器的物件圖;記錄器和處理器的詳細程度可以透過僅設定級別(以及在記錄器的情況下,傳播標誌)來控制。在多執行緒環境中以安全的方式任意更改物件圖是有問題的;雖然並非不可能,但其帶來的好處不值得在實現中增加複雜性。
因此,當配置字典的 incremental
鍵存在且為 True
時,系統將完全忽略任何 formatters
和 filters
條目,並且僅處理 handlers
條目中的 level
設定,以及 loggers
和 root
條目中的 level
和 propagate
設定。
在配置字典中使用值允許將配置作為 pickled 字典透過網路傳送到套接字偵聽器。因此,可以在無需停止和重啟應用程式的情況下,隨著時間的推移更改長時間執行的應用程式的日誌詳細程度。
物件連線¶
該模式描述了一組日誌物件 - 記錄器、處理器、格式化器、過濾器 - 它們在物件圖中相互連線。因此,該模式需要表示物件之間的連線。例如,假設在配置完成後,特定的記錄器附加了特定的處理器。為了便於討論,我們可以說記錄器表示源,而處理器表示這兩個連線之間的目標。當然,在配置的物件中,這表示為記錄器持有對處理器的引用。在配置字典中,這是透過給每個目標物件一個唯一標識它的 ID 來完成的,然後在源物件的配置中使用該 ID 來指示源物件和具有該 ID 的目標物件之間存在連線。
因此,例如,考慮以下 YAML 程式碼片段:
formatters:
brief:
# configuration for formatter with id 'brief' goes here
precise:
# configuration for formatter with id 'precise' goes here
handlers:
h1: #This is an id
# configuration of handler with id 'h1' goes here
formatter: brief
h2: #This is another id
# configuration of handler with id 'h2' goes here
formatter: precise
loggers:
foo.bar.baz:
# other configuration for logger 'foo.bar.baz'
handlers: [h1, h2]
(注意:這裡使用 YAML 是因為它比字典的等效 Python 原始碼形式更易讀。)
記錄器的 ID 是以程式設計方式用於獲取對這些記錄器的引用的記錄器名稱,例如 foo.bar.baz
。格式化器和過濾器的 ID 可以是任何字串值(例如上面的 brief
,precise
),並且它們是瞬態的,因為它們僅在處理配置字典時有意義,用於確定物件之間的連線,並且在配置呼叫完成後不會持久儲存在任何地方。
上面的程式碼片段表明,名為 foo.bar.baz
的記錄器應該附加兩個處理器,它們由處理器 ID h1
和 h2
描述。h1
的格式化器是由 ID brief
描述的格式化器,h2
的格式化器是由 ID precise
描述的格式化器。
使用者定義的物件¶
該模式支援用於處理器、過濾器和格式化器的使用者定義物件。(記錄器不需要針對不同的例項具有不同的型別,因此此配置模式不支援使用者定義的記錄器類。)
要配置的物件由詳細說明其配置的字典描述。在某些情況下,日誌系統可以從上下文中推斷出如何例項化物件,但是當要例項化使用者定義的物件時,系統將不知道如何執行此操作。為了為使用者定義的物件例項化提供完全的靈活性,使用者需要提供一個“工廠” - 一個可呼叫物件,該物件使用配置字典呼叫並返回例項化的物件。這透過在特殊鍵 '()'
下提供工廠的絕對匯入路徑來指示。這是一個具體的示例:
formatters:
brief:
format: '%(message)s'
default:
format: '%(asctime)s %(levelname)-8s %(name)-15s %(message)s'
datefmt: '%Y-%m-%d %H:%M:%S'
custom:
(): my.package.customFormatterFactory
bar: baz
spam: 99.9
answer: 42
上面的 YAML 程式碼片段定義了三個格式化器。第一個,ID 為 brief
,是一個標準的 logging.Formatter
例項,具有指定的格式字串。第二個,ID 為 default
,具有更長的格式,並且還顯式定義了時間格式,並且將導致使用這兩個格式字串初始化的 logging.Formatter
。以 Python 原始碼形式顯示,brief
和 default
格式化器具有配置子字典:
{
'format' : '%(message)s'
}
和
{
'format' : '%(asctime)s %(levelname)-8s %(name)-15s %(message)s',
'datefmt' : '%Y-%m-%d %H:%M:%S'
}
分別地,由於這些字典不包含特殊鍵 '()'
,因此例項化是從上下文中推斷出來的:結果,建立了標準的 logging.Formatter
例項。第三個格式化器(ID 為 custom
)的配置子字典為:
{
'()' : 'my.package.customFormatterFactory',
'bar' : 'baz',
'spam' : 99.9,
'answer' : 42
}
並且此字典包含特殊鍵 '()'
,這意味著需要使用者定義的例項化。在這種情況下,將使用指定的工廠可呼叫物件。如果它是一個實際的可呼叫物件,它將被直接使用 - 否則,如果你指定一個字串(如示例中所示),將使用正常的匯入機制來定位實際的可呼叫物件。可呼叫物件將使用配置子字典中的 剩餘 項作為關鍵字引數進行呼叫。在上面的示例中,ID 為 custom
的格式化器將被假定為由以下呼叫返回:
my.package.customFormatterFactory(bar='baz', spam=99.9, answer=42)
警告
在上面的示例中,諸如 bar
、spam
和 answer
等鍵的值不應是配置字典或引用,例如 cfg://foo
或 ext://bar
,因為它們不會被配置機制處理,而是按原樣傳遞給可呼叫物件。
鍵 '()'
被用作特殊鍵,因為它不是有效的關鍵字引數名稱,因此不會與呼叫中使用的關鍵字引數名稱衝突。'()'
也可以作為助記符,表示相應的值是可呼叫的。
在 3.11 版本中更改: handlers
和 loggers
的 filters
成員除了 ID 之外,還可以接受過濾器例項。
您還可以指定一個特殊鍵 '.'
,其值是一個字典,用於對映屬性名稱到值。如果找到,指定的屬性將在返回使用者定義的物件之前設定。因此,使用以下配置
{
'()' : 'my.package.customFormatterFactory',
'bar' : 'baz',
'spam' : 99.9,
'answer' : 42,
'.' {
'foo': 'bar',
'baz': 'bozz'
}
}
返回的格式化程式將具有設定為 'bar'
的屬性 foo
和設定為 'bozz'
的屬性 baz
。
警告
在上面的示例中,諸如 foo
和 baz
等屬性的值不應是配置字典或引用,例如 cfg://foo
或 ext://bar
,因為它們不會被配置機制處理,而是按原樣設定為屬性值。
處理程式配置順序¶
處理程式按照其鍵的字母順序配置,並且配置的處理程式將替換架構中 handlers
字典(工作副本)中的配置字典。如果您使用諸如 cfg://handlers.foo
之類的結構,那麼最初 handlers['foo']
指向名為 foo
的處理程式的配置字典,稍後(一旦配置了該處理程式)它會指向配置的處理程式例項。因此,cfg://handlers.foo
可以解析為字典或處理程式例項。一般來說,最好以這樣一種方式命名處理程式,使得依賴的處理程式在它們所依賴的任何處理程式之後 _配置_ ;這允許在配置依賴於處理程式 foo
的處理程式時使用類似 cfg://handlers.foo
的東西。如果該依賴的處理程式被命名為 bar
,則會產生問題,因為 bar
的配置將在 foo
的配置之前嘗試,並且 foo
尚未配置。但是,如果依賴的處理程式被命名為 foobar
,它將在 foo
之後配置,結果是 cfg://handlers.foo
將解析為已配置的處理程式 foo
,而不是其配置字典。
訪問外部物件¶
有時配置需要引用配置外部的物件,例如 sys.stderr
。如果使用 Python 程式碼構造配置字典,這很簡單,但是當透過文字檔案(例如 JSON、YAML)提供配置時,就會出現問題。在文字檔案中,沒有標準方法可以將 sys.stderr
與字面字串 'sys.stderr'
區分開來。為了方便這種區分,配置系統會在字串值中查詢某些特殊字首並對其進行特殊處理。例如,如果字面字串 'ext://sys.stderr'
作為配置中的值提供,那麼 ext://
將被剝離,值的其餘部分將使用正常的匯入機制進行處理。
這種字首的處理方式類似於協議處理:有一個通用機制來查詢與正則表示式 ^(?P<prefix>[a-z]+)://(?P<suffix>.*)$
匹配的字首,其中,如果 prefix
被識別,則 suffix
將以依賴於字首的方式處理,並且處理的結果將替換字串值。如果字首未被識別,則字串值將保持不變。
訪問內部物件¶
除了外部物件之外,有時還需要引用配置中的物件。配置系統會隱式地為它知道的事物這樣做。例如,記錄器或處理程式中 level
的字串值 'DEBUG'
將自動轉換為值 logging.DEBUG
,並且 handlers
、filters
和 formatter
條目將採用物件 ID 並解析為相應的目標物件。
但是,對於 logging
模組未知的使用者定義物件,需要更通用的機制。例如,考慮 logging.handlers.MemoryHandler
,它接受一個 target
引數,該引數是另一個要委託的處理程式。由於系統已經知道這個類,那麼在配置中,給定的 target
只需要是相關目標處理程式的物件 ID,系統將從 ID 解析到該處理程式。但是,如果使用者定義了一個具有 alternate
處理程式的 my.package.MyHandler
,配置系統將不知道 alternate
指的是處理程式。為了滿足這一點,通用解析系統允許使用者指定
handlers:
file:
# configuration of file handler goes here
custom:
(): my.package.MyHandler
alternate: cfg://handlers.file
字面字串 'cfg://handlers.file'
的解析方式與帶有 ext://
字首的字串類似,但在配置本身中查詢而不是在匯入名稱空間中查詢。該機制允許透過點或索引進行訪問,類似於 str.format
提供的訪問方式。因此,給定以下片段
handlers:
email:
class: logging.handlers.SMTPHandler
mailhost: localhost
fromaddr: my_app@domain.tld
toaddrs:
- support_team@domain.tld
- dev_team@domain.tld
subject: Houston, we have a problem.
在配置中,字串 'cfg://handlers'
將解析為鍵為 handlers
的字典,字串 'cfg://handlers.email
將解析為 handlers
字典中鍵為 email
的字典,依此類推。字串 'cfg://handlers.email.toaddrs[1]
將解析為 'dev_team@domain.tld'
,字串 'cfg://handlers.email.toaddrs[0]'
將解析為值 'support_team@domain.tld'
。subject
值可以使用 'cfg://handlers.email.subject'
或等效的 'cfg://handlers.email[subject]'
來訪問。只有當鍵包含空格或非字母數字字元時才需要使用後一種形式。請注意,字元 [
和 ]
不允許出現在鍵中。如果索引值僅由十進位制數字組成,則將嘗試使用相應的整數值進行訪問,如果需要,則回退到字串值。
給定字串 cfg://handlers.myhandler.mykey.123
,它將解析為 config_dict['handlers']['myhandler']['mykey']['123']
。如果字串被指定為 cfg://handlers.myhandler.mykey[123]
,系統將嘗試從 config_dict['handlers']['myhandler']['mykey'][123]
中檢索值,如果失敗,則回退到 config_dict['handlers']['myhandler']['mykey']['123']
。
匯入解析和自定義匯入器¶
預設情況下,匯入解析使用內建的 __import__()
函式來進行匯入。您可能希望用自己的匯入機制替換它:如果是這樣,您可以替換 DictConfigurator
或其超類 BaseConfigurator
類的 importer
屬性。但是,您需要小心,因為函式是透過描述符從類中訪問的。如果您使用 Python 可呼叫物件來進行匯入,並且希望在類級別而不是例項級別定義它,則需要使用 staticmethod()
對其進行包裝。例如
from importlib import import_module
from logging.config import BaseConfigurator
BaseConfigurator.importer = staticmethod(import_module)
如果您在配置器例項上設定匯入可呼叫物件,則無需使用 staticmethod()
進行包裝。
配置 QueueHandler 和 QueueListener¶
如果您想配置一個 QueueHandler
,請注意,這通常與 QueueListener
結合使用,您可以將兩者一起配置。配置完成後,QueueListener
例項將作為建立的處理程式的 listener
屬性可用,並且您可以使用 getHandlerByName()
並傳遞您在配置中用於 QueueHandler
的名稱來訪問它。用於配置該對的字典模式如下面的 YAML 片段示例所示。
handlers:
qhand:
class: logging.handlers.QueueHandler
queue: my.module.queue_factory
listener: my.package.CustomListener
handlers:
- hand_name_1
- hand_name_2
...
queue
和 listener
鍵是可選的。
如果存在 queue
鍵,則對應的值可以是以下之一
一個實現
Queue.put_nowait
和Queue.get
公共 API 的物件。例如,這可能是queue.Queue
的實際例項或其子類,或透過multiprocessing.managers.SyncManager.Queue()
獲取的代理。當然,只有在程式碼中構造或修改配置字典時才有可能。
一個字串,解析為一個可呼叫物件,當不帶引數呼叫時,返回要使用的佇列例項。該可呼叫物件可以是
queue.Queue
子類或返回合適的佇列例項的函式,例如my.module.queue_factory()
。一個具有
'()'
鍵的字典,該字典以通常的方式構造,如 使用者定義的物件 中所述。此構造的結果應為queue.Queue
例項。
如果缺少 queue
鍵,則會建立並使用標準的無界 queue.Queue
例項。
如果存在 listener
鍵,則對應的值可以是以下之一
logging.handlers.QueueListener
的子類。當然,只有在程式碼中構造或修改配置字典時才有可能。一個字串,解析為一個類,該類是
QueueListener
的子類,例如'my.package.CustomListener'
。一個具有
'()'
鍵的字典,該字典以通常的方式構造,如 使用者定義的物件 中所述。此構造的結果應為具有與QueueListener
初始化器相同簽名的可呼叫物件。
如果缺少 listener
鍵,則使用 logging.handlers.QueueListener
。
handlers
鍵下的值是配置中其他處理程式的名稱(未在上面的程式碼片段中顯示),這些處理程式將傳遞給佇列監聽器。
任何自定義的佇列處理程式和監聽器類都需要使用與 QueueHandler
和 QueueListener
相同的初始化簽名進行定義。
在 3.12 版本中新增。
配置檔案格式¶
fileConfig()
理解的配置檔案格式基於 configparser
功能。該檔案必須包含名為 [loggers]
、[handlers]
和 [formatters]
的節,這些節按名稱標識檔案中定義的每種型別的實體。對於每個這樣的實體,都有一個單獨的節,用於標識該實體是如何配置的。因此,對於 [loggers]
節中名為 log01
的記錄器,相關的配置詳細資訊儲存在 [logger_log01]
節中。類似地,[handlers]
節中名為 hand01
的處理程式的配置儲存在名為 [handler_hand01]
的節中,而 [formatters]
節中名為 form01
的格式化程式的配置在名為 [formatter_form01]
的節中指定。根記錄器配置必須在名為 [logger_root]
的節中指定。
注意
fileConfig()
API 比 dictConfig()
API 更舊,並且不提供涵蓋日誌記錄某些方面的功能。例如,您不能使用 fileConfig()
配置 Filter
物件,這些物件提供了超出簡單整數級別的訊息過濾。如果您的日誌配置中需要 Filter
的例項,則需要使用 dictConfig()
。請注意,對配置功能的未來增強將新增到 dictConfig()
,因此在方便的時候考慮過渡到這個較新的 API 是值得的。
下面給出了檔案中這些節的示例。
[loggers]
keys=root,log02,log03,log04,log05,log06,log07
[handlers]
keys=hand01,hand02,hand03,hand04,hand05,hand06,hand07,hand08,hand09
[formatters]
keys=form01,form02,form03,form04,form05,form06,form07,form08,form09
根記錄器必須指定一個級別和處理程式列表。下面給出了根記錄器節的示例。
[logger_root]
level=NOTSET
handlers=hand01
level
條目可以是 DEBUG、INFO、WARNING、ERROR、CRITICAL
或 NOTSET
之一。僅對於根記錄器,NOTSET
表示將記錄所有訊息。級別值在 logging
包的名稱空間上下文中進行評估。
handlers
條目是一個逗號分隔的處理程式名稱列表,這些名稱必須出現在 [handlers]
節中。這些名稱必須出現在 [handlers]
節中,並且在配置檔案中具有對應的節。
對於根記錄器以外的記錄器,需要一些額外的資訊。以下示例說明了這一點。
[logger_parser]
level=DEBUG
handlers=hand01
propagate=1
qualname=compiler.parser
level
和 handlers
條目的解釋方式與根記錄器相同,但如果非根記錄器的級別被指定為 NOTSET
,系統會查詢層次結構中更高級別的記錄器,以確定該記錄器的有效級別。propagate
條目設定為 1 表示訊息必須從該記錄器傳播到記錄器層次結構中更高級別的處理程式,設定為 0 表示訊息不會傳播到層次結構中更高級別的處理程式。qualname
條目是記錄器的分層通道名稱,也就是說,應用程式用來獲取記錄器的名稱。
以下示例說明了指定處理程式配置的部分。
[handler_hand01]
class=StreamHandler
level=NOTSET
formatter=form01
args=(sys.stdout,)
class
條目指示處理程式的類(由 eval()
在 logging
包的名稱空間中確定)。level
的解釋方式與記錄器相同,NOTSET
被視為“記錄一切”。
formatter
條目指示此處理程式的格式化器的鍵名。如果為空,則使用預設格式化器 (logging._defaultFormatter
)。如果指定了名稱,則它必須出現在 [formatters]
部分中,並且在配置檔案中具有相應的節。
args
條目在 在 logging
包的名稱空間中進行評估後,是處理程式類建構函式的引數列表。請參閱相關處理程式的建構函式,或下面的示例,瞭解如何構造典型的條目。如果未提供,則預設為 ()
。
可選的 kwargs
條目在 在 logging
包的名稱空間中進行評估後,是處理程式類建構函式的關鍵字引數字典。如果未提供,則預設為 {}
。
[handler_hand02]
class=FileHandler
level=DEBUG
formatter=form02
args=('python.log', 'w')
[handler_hand03]
class=handlers.SocketHandler
level=INFO
formatter=form03
args=('localhost', handlers.DEFAULT_TCP_LOGGING_PORT)
[handler_hand04]
class=handlers.DatagramHandler
level=WARN
formatter=form04
args=('localhost', handlers.DEFAULT_UDP_LOGGING_PORT)
[handler_hand05]
class=handlers.SysLogHandler
level=ERROR
formatter=form05
args=(('localhost', handlers.SYSLOG_UDP_PORT), handlers.SysLogHandler.LOG_USER)
[handler_hand06]
class=handlers.NTEventLogHandler
level=CRITICAL
formatter=form06
args=('Python Application', '', 'Application')
[handler_hand07]
class=handlers.SMTPHandler
level=WARN
formatter=form07
args=('localhost', 'from@abc', ['user1@abc', 'user2@xyz'], 'Logger Subject')
kwargs={'timeout': 10.0}
[handler_hand08]
class=handlers.MemoryHandler
level=NOTSET
formatter=form08
target=
args=(10, ERROR)
[handler_hand09]
class=handlers.HTTPHandler
level=NOTSET
formatter=form09
args=('localhost:9022', '/log', 'GET')
kwargs={'secure': True}
以下示例說明了指定格式化器配置的部分。
[formatter_form01]
format=F1 %(asctime)s %(levelname)s %(message)s %(customfield)s
datefmt=
style=%
validate=True
defaults={'customfield': 'defaultvalue'}
class=logging.Formatter
格式化器配置的引數與字典模式 formatters 部分中的鍵相同。
defaults
條目在 在 logging
包的名稱空間中進行評估後,是用於自定義格式化欄位的預設值的字典。如果未提供,則預設為 None
。
注意
由於使用了上述的 eval()
,透過套接字使用 listen()
傳送和接收配置會產生潛在的安全風險。風險僅限於多個不互信的使用者在同一臺機器上執行程式碼的情況;有關更多資訊,請參閱 listen()
文件。
另請參閱
- 模組
logging
logging 模組的 API 參考。
- 模組
logging.handlers
logging 模組包含的有用處理程式。