Python中Warning Control的一些理解

寫在前面

最近在pytorch運(yùn)行網(wǎng)絡(luò)模型時(shí),因?yàn)榘姹镜膯栴},有大量的warning輸出,這對(duì)于根據(jù)輸出查看訓(xùn)練狀態(tài)來說是很麻煩的,所以有了忽略warning輸出的需求.

Python中的warning Control

基本概念

warning類型分類

Python中有多種warning類型,其中Warning為其他所有warning類型的基類.詳情如下:

  • UserWarning: 用戶警告
  • DeprecationWarning:棄用警告
  • SyntaxWarning: 語法警告
  • RuntimeWarning: 運(yùn)行時(shí)警告
  • FutureWarning: 未來可能發(fā)生的警告
  • PendingDeprecationWarning: 未來可能被棄用的警告
  • ImportWarning: 導(dǎo)入警告
  • UnicodeWarning: 與Unicode編碼相關(guān)的警告
  • BytesWarning: 與字節(jié)或者字節(jié)數(shù)組相關(guān)的警告
  • ResourceWarning: 與資源使用相關(guān)的警告

詳情可查看此處

warning filter

警告過濾器可以理解為是一個(gè)表中的一個(gè)條目,格式為(action, message, category, module, lineno),其中,action表示匹配到的警告采用什么樣的頻率輸出, message表示警告輸出信息,此處是一個(gè)正則匹配項(xiàng),category表示匹配的warning類型, module表示警告發(fā)出所在的模塊名,也是正則匹配項(xiàng), lineno表示警告發(fā)出的行號(hào),只有(message, category, module, lineno)都匹配到發(fā)出的警告時(shí),相應(yīng)的action才會(huì)進(jìn)行.此處我們需要簡(jiǎn)單的理解一個(gè)警告發(fā)出的過程

  1. 首先調(diào)用warnings.warn(message, category)表示此處有個(gè)警告需發(fā)出
  2. 根據(jù)警告請(qǐng)求的message, category, lineno, module信息作為索引, 以在warning filter構(gòu)成的列表中尋找匹配項(xiàng),找到匹配的filter, 然后對(duì)該類型的警告執(zhí)行action操作,如果沒有匹配的filter則對(duì)該類型警告執(zhí)行默認(rèn)操作.

因此我們可以看出warning filter的作用是用于控制警告的輸出動(dòng)作.

action分類

action表示對(duì)于將發(fā)出的警告需執(zhí)行的動(dòng)作,包含著輸出的頻率

  • default: 對(duì)于匹配的警告,打印在每個(gè)位置第一次出現(xiàn)時(shí)輸出(模塊+行號(hào)),之后在同一位置出現(xiàn)時(shí)不輸出.
  • error: 將匹配的警告變?yōu)楫惓?/li>
  • ignore: 忽略警告,不進(jìn)行輸出
  • always: 總是打印輸出匹配的警告
  • module: 對(duì)于匹配到的警告,在一個(gè)模塊中第一次出現(xiàn)時(shí)才輸出(與行號(hào)無關(guān)),之后不管在模塊的哪個(gè)位置出現(xiàn)都不輸出.
  • once: 對(duì)于匹配到的警告只打印輸出一次,而不管在哪個(gè)位置.

warn代碼原理剖析

警告發(fā)出的關(guān)鍵方法是warnings.warn(),在warnings.py文件中,因此可以深入去理解該部分代碼,部分進(jìn)行了省略.

def warn(message, category=None, stacklevel=1, source=None):
    # 1.類型檢查
    # 2.設(shè)置行號(hào),設(shè)置模塊名, 設(shè)置文件名
    registry = globals.setdefault("__warningregistry__", {})
    warn_explicit(message, category, filename, lineno, module, registry,
                  globals, source)

def warn_explicit(message, category, filename, lineno,
                  module=None, registry=None, module_globals=None,
                  source=None):
    # 3.獲取警告信息,設(shè)置行號(hào),構(gòu)建一個(gè)key
    key = (text, category, lineno)
    if registry.get(key):  # registry是一個(gè)字典,保存了執(zhí)行once,module,default操作的警告請(qǐng)求
        return
    # 4.遍歷filter列表,尋找匹配項(xiàng)
    for item in filters:
        action, msg, cat, mod, ln = item
        if ((msg is None or msg.match(text)) and
            issubclass(category, cat) and
            (mod is None or mod.match(module)) and
            (ln == 0 or lineno == ln)):
            break
    else:
        action = defaultaction # 沒有找到匹配的filter則使用default操作
    # 5.根據(jù)對(duì)應(yīng)的action執(zhí)行是否輸出警告的操作
    if action == "ignore":
        return
    if action == "error":
        raise message
    if action == "once":
        registry[key] = 1
        oncekey = (text, category)
        if onceregistry.get(oncekey):
            return
        onceregistry[oncekey] = 1
    elif action == "always":
        pass
    elif action == "module":
        registry[key] = 1
        altkey = (text, category, 0)
        if registry.get(altkey):
            return
        registry[altkey] = 1
    elif action == "default":
        registry[key] = 1
    else:
        # 不能處理的錯(cuò)誤
        raise RuntimeError(
              "Unrecognized action (%r) in warnings.filters:\n %s" %
              (action, item))
    # 6. 按格式輸出警告信息
    msg = WarningMessage(message, category, filename, lineno, source)
    _showwarnmsg(msg)

注意: 在python2, 和python3中,略有不同,python2使用的是warnings.py所定義的方法,而在python3中雖然也提供了warnings.py,但是在warnings.py中導(dǎo)入了_warnings模塊,所以實(shí)際上python3中使用的warn方法定義在_warning模塊中,而模塊_warnings是在python虛擬機(jī)初始化中創(chuàng)建的模塊對(duì)象,也就是說用C語言內(nèi)置在python虛擬機(jī)中....不過我們可以將warnings.py中的模塊_warnings導(dǎo)入注釋掉,從而使用warnings.py中定義的方法.

警告控制的一些實(shí)踐

在理解python的警告控制相關(guān)的原理后,我們便能夠根據(jù)自己的需要控制警告信息如何輸出,因此從中,我們可以知道控制警告的關(guān)鍵便是如何設(shè)置warning filter.設(shè)置filter的方式有兩種,一是在代碼中,二是啟動(dòng)虛擬機(jī)時(shí)使用命令行參數(shù)

warnings.filterwarnings方法

在源代碼中,調(diào)用warnings.filterwarnings()函數(shù)設(shè)置filter條目,示例如下

# 以下在python3
import warnings

def f():
    warnings.warn("warn occur!", UserWarning)

warnings.filterwarnings('module', category=UserWarning)
print(warnings.filters)
f()
print('hello')
for i in range(3):
    f()
print('world!')
# 輸出結(jié)果
[('module', None, <class 'UserWarning'>, None, 0), ('default', None, <class 'DeprecationWarning'>, '__main__', 0), ('ignore', None, <class 'DeprecationWarning'>, None, 0), ('ignore', None, <class 'PendingDeprecationWarning'>, None, 0), ('ignore', None, <class 'ImportWarning'>, None, 0), ('ignore', None, <class 'ResourceWarning'>, None, 0)]
test.py:4: UserWarning: warn occur!
  warnings.warn("warn occur!", UserWarning)
hello
world!

注意: filter設(shè)置必須在發(fā)出警告請(qǐng)求之前

命令行參數(shù) -W

在啟動(dòng)虛擬機(jī)時(shí)使用-W參數(shù)同樣可以設(shè)置filter條目,參數(shù)格式如下

-W action:message:category:module:lineno
其中各部分含義與warning filter條目設(shè)置各項(xiàng)含義相同

注意: 如果某項(xiàng)缺省,如message,module,lineno缺省則參數(shù)形式為-W ignore::UserWarning,其中UserWarning后面部分的符號(hào):可以省略,但是前面的不行.

注意

python提供的警告控制也有著局限性,只有對(duì)于使用了warnings.warn()函數(shù)發(fā)出的警告,可以通過設(shè)置warning filter條目控制警告輸出,但是對(duì)于一些使用底層函數(shù)進(jìn)行警告輸出的信息無法控制,例如在pytorch中,一些涉及到tensor操作的函數(shù)以底層C/C++實(shí)現(xiàn),并且將警告信息嵌入其中,對(duì)于這種情況輸出警告信息,我們沒法控制,所以如果不想看輸出的警告信息,還是乖乖根據(jù)警告提示修改代碼吧_

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市籍琳,隨后出現(xiàn)的幾起案子次企,更是在濱河造成了極大的恐慌芹务,老刑警劉巖万搔,帶你破解...
    沈念sama閱讀 206,839評(píng)論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件魁索,死亡現(xiàn)場(chǎng)離奇詭異迈勋,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)瘫想,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,543評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門仗阅,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人国夜,你說我怎么就攤上這事减噪。” “怎么了车吹?”我有些...
    開封第一講書人閱讀 153,116評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵筹裕,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我窄驹,道長(zhǎng)朝卒,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,371評(píng)論 1 279
  • 正文 為了忘掉前任乐埠,我火速辦了婚禮抗斤,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘丈咐。我一直安慰自己瑞眼,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,384評(píng)論 5 374
  • 文/花漫 我一把揭開白布棵逊。 她就那樣靜靜地躺著伤疙,像睡著了一般。 火紅的嫁衣襯著肌膚如雪歹河。 梳的紋絲不亂的頭發(fā)上掩浙,一...
    開封第一講書人閱讀 49,111評(píng)論 1 285
  • 那天花吟,我揣著相機(jī)與錄音秸歧,去河邊找鬼。 笑死衅澈,一個(gè)胖子當(dāng)著我的面吹牛键菱,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播今布,決...
    沈念sama閱讀 38,416評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼经备,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了部默?” 一聲冷哼從身側(cè)響起侵蒙,我...
    開封第一講書人閱讀 37,053評(píng)論 0 259
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎傅蹂,沒想到半個(gè)月后纷闺,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體算凿,經(jīng)...
    沈念sama閱讀 43,558評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,007評(píng)論 2 325
  • 正文 我和宋清朗相戀三年犁功,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了氓轰。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,117評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡浸卦,死狀恐怖署鸡,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情限嫌,我是刑警寧澤靴庆,帶...
    沈念sama閱讀 33,756評(píng)論 4 324
  • 正文 年R本政府宣布,位于F島的核電站怒医,受9級(jí)特大地震影響撒穷,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜裆熙,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,324評(píng)論 3 307
  • 文/蒙蒙 一端礼、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧入录,春花似錦蛤奥、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,315評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至蚀同,卻和暖如春缅刽,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背蠢络。 一陣腳步聲響...
    開封第一講書人閱讀 31,539評(píng)論 1 262
  • 我被黑心中介騙來泰國(guó)打工衰猛, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人刹孔。 一個(gè)月前我還...
    沈念sama閱讀 45,578評(píng)論 2 355
  • 正文 我出身青樓啡省,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親髓霞。 傳聞我的和親對(duì)象是個(gè)殘疾皇子卦睹,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,877評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容

  • mean to add the formatted="false" attribute?.[ 46% 47325/...
    ProZoom閱讀 2,693評(píng)論 0 3
  • 常用模塊 認(rèn)識(shí)模塊 什么是模塊 什么是模塊结序? 常見的場(chǎng)景:一個(gè)模塊就是一個(gè)包含了python定義和聲明的文件,文...
    go以恒閱讀 1,938評(píng)論 0 6
  • Python語言特性 1 Python的函數(shù)參數(shù)傳遞 看兩個(gè)如下例子纵潦,分析運(yùn)行結(jié)果: 代碼一: a = 1 def...
    伊森H閱讀 3,048評(píng)論 0 15
  • 前言 在自動(dòng)化測(cè)試實(shí)踐過程中徐鹤,必不可少的就是進(jìn)行日志管理配喳,方便調(diào)試和生產(chǎn)問題追蹤,python提供了logg...
    苦葉子閱讀 806評(píng)論 0 0
  • 蘇軾詩(shī)詞
    田間一棵苗閱讀 293評(píng)論 3 7