国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

python logging 日志重復打印問題定位

crossea / 3335人閱讀

摘要:在同一系統中我們有時要用到這種機制來方便日志打印,因此有時會不同進程使用同一前綴名來初始化。避免日志重復的原則是在名有相同前綴的情況下對于一個模塊兩個進程調的情況,涉及到會被其他進程的模塊,不應觸發任何同名前綴的的操作。

圖:

圖編號按順序1-4,嫌長可以跳過定位過程看總結

定位過程:

我司項目幾個服務進程的初始化log都是這樣的:

這些進程都會初始化一個叫 sdsomlogger,并且把handler加到了這個logger對象中,后面getlogger的時候我們是 sdsom.xx, 這個按點分隔會導致認為是子logger,比如是sdsom.A,就會新建一個loggersdsom.A,然后把 sdsom 這個logger設為它的parent(圖1),打日志的時候,會一直往上遍歷,把所有parent的所有handler都打一遍(圖2)。這些實例進程間是獨立的,但如果在一個進程里,比如在A進程中 import 了 B 的模塊,而這個模塊 import 了B自己的log.py模塊,觸發一次 addHandler (圖3),就把 B 的 handler 加進了 A進程的 sdsom logger里(把它設為了parent),所以 A 的 sdsom logger里有兩個handler (圖4),于是A 的log同時打到了B的日志文件里。(注意對比圖3 圖4的對象地址 是一致的)

這個logger父子關系前人要這么用的原因,我估計是我們項目的common這個模塊,用父子關系可以實現這樣一個方式:不需另外初始化,log = logging.getLogger("sdsom.common") 只需要執行這一句,這個loggerparent就被設為 <import這個common模塊的> 進程的 sdsom logger,實際上sdsom.xxx 點號后面的內容都沒有影響了,這個common logger打印時,會調parent,于是也就被相應進程的handler打印了。
本身也算方便的機制,但由于這種方式內部實現不可見, 容易誤用。

如果要共享日志, 還有一種方式就是對相應的logger顯式加handler
比如要在其他日志里打印zerorpc的日志, 我們大部分日志初始化處都有這句: logging.getLogger("zerorpc").addHandler(handler), 給rpcLogger加上自己的handler就可以了,由于有了handler,那么只要zerorpc的源碼里是getLogger("zerorpc")的(實際源碼中一般是getLogger(__name__),在包內__name__即為"zerorpc.xxx"),日志就能打印到對應進程的日志里。
所以我們完全可以不用父子關系,而是像zerorpc一樣在進程logger初始化的地方加上:
logging.getLogger("common").addHandler(handler)
然后common里的模塊直接log = logging.getLogger("common")用即可,為避免和三方庫重復要注意一下命名
當然還有一種方式就是自己的handler也通過函數觸發,不要在模塊全局上執行,加入一個函數手動調,只在進程初始化時調。

總結:

logging的父子關系是一個基礎機制,稍微看下源碼即可理解(其實主要就是圖1圖2):以點號.分隔,取最后一個點號的左邊為前綴,以此前綴名作父,一個logger觸發記錄時,會調用所有父親的handler。在同一系統中我們有時要用到這種機制來方便日志打印,因此有時會不同進程使用同一前綴名來初始化logger。這時,不同進程的模塊若有相互import,容易造成一個日志打到多個日志文件里。如:

進程A:
A.py:
logger = logging.getLogger("xxsystem.A")
logger.addHandler(logging.FileHandler("service1.log"))
進程B 兩個模塊:

B.py:
from C import func
logger = logging.getLogger("xxsystem.B")
logger.addHandler(logging.FileHandler("service2.log"))

C.py:
from A import func

這樣,就會造成B進程的log總是同時打到兩個service1.log, service2.log日志文件里。這里是簡化環境,只要B的import樹里有A模塊,就會造成同樣結果。

避免日志重復的原則是:
logger名有相同前綴的情況下,對于一個模塊兩個進程調的情況,涉及到會被其他進程import的模塊,不應觸發任何同名前綴的loggeraddHandler操作。 (不能import <調用了addHandler方法的> 模塊,自身也不能執行getLogger(prefix).addHandler

實際上我司使用這種機制本來也沒有什么問題,只要注意不要隨便import,都用getLogger即可。但由于代碼不規范還是出現了不應有的import 日志初始化模塊的情況。

要達到:

哪個進程調用模塊,日志就打在那個進程對應的日志里:
a)getLogger,只要前綴相同,就會把當前進程的"prefix" logger設為父, 由于上面說的原因,這個logger會且只會被打到調用它的進程中(自己的handler沒有初始化過)
b)logger對象

無論哪個進程調用模塊,日志都打在自己規劃所屬的進程對應日志里:
不要有任何父子關系, 日志名不要帶點。這時反過來,必須調用日志初始化模塊觸發初始化,而不能只用getLogger, 否則是一個空logger,哪里都不會打印。

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/44962.html

相關文章

  • 基于Selenium + Python的web自動化框架

    摘要:一什么是是一個基于瀏覽器的自動化工具,她提供了一種跨平臺跨瀏覽器的端到端的自動化解決方案。模塊主要用來記錄用例執行情況,以便于高效的調查用例失敗信息以及追蹤用例執行情況。測試用例倉庫用例倉庫主要用來組織自動化測試用例。 一、什么是Selenium? Selenium是一個基于瀏覽器的自動化工具,她提供了一種跨平臺、跨瀏覽器的端到端的web自動化解決方案。Selenium主要包括三部分:...

    sunny5541 評論0 收藏0
  • Python中的logging模塊

    摘要:最近修改了項目里的相關功能,用到了標準庫里的模塊,在此做一些記錄。可能沒有線程名。可能沒有用戶輸出的消息日志級別有如下級別,,,,默認級別是,模塊只會輸出指定以上的。在或者中這是很常見的方式。正常的做法應該是全局只配置一次。 最近修改了項目里的logging相關功能,用到了python標準庫里的logging模塊,在此做一些記錄。主要是從官方文檔和stackoverflow上查詢到的一...

    zsirfs 評論0 收藏0
  • pythonlogging 模塊淺析

    摘要:的繼承關系使用做日志輸出時,首先我們需要一個創建一個對象。再設計多級別的日志系統時,尤其要注意這點。當然,這樣做其實是有悖于的本意的。是什么是一個程序內全局唯一的,所有對象的祖先。因此,直接修改是危險的。 0x00 python logging的繼承關系 使用python做日志輸出時,首先我們需要一個創建一個Logger對象:import logging; logger = log...

    cooxer 評論0 收藏0
  • Unity命令行模式,也能「日志實時輸出」

    摘要:類似這樣執行打印最終輸出的日志要想在命令行模式工作的時候,查看它的編譯進度,霖哥一般會遠程跑進執行編譯工作的機器,然后用命令,把它的日志實時輸出來嗯,這相當的不科學啊。我是霖哥,一個商學院畢業的程序員,一個游戲開發工程師。 showImg(https://segmentfault.com/img/remote/1460000008856262); 如果你使用過Unity命令行模式(ba...

    whjin 評論0 收藏0
  • python學習筆記-裝飾器

    摘要:裝飾器介紹中的裝飾器的目的是為一個目標函數添加額外的功能卻不修改函數本身。裝飾器的本身其實是一個特殊的函數。那么有啥更好的解決方式呢裝飾器代碼像上面這么寫,可以較好地解決了上面提到的第一個問題。裝飾器語法糖放在函數前面,相當于執行了等。 怎么理解python中的裝飾器 一個比喻 知乎上有一個比較形象的比喻 https://www.zhihu.com/questio...:人類穿著內褲很...

    張金寶 評論0 收藏0

發表評論

0條評論

最新活動
閱讀需要支付1元查看
<