有一個錯誤在你的Python的模塊理解(如果我可以調用它的):
我認爲,在Python中,當您導入在兩個不同的腳本在同一個模塊,它們是完全斷開,因爲第一個變成myapp.logging
,第二個變成mylib.logging
。
事實並非如此。
的import
語句解釋時遇到它,當你在你的主程序(python myapp.py
或同等)運行python,執行這些行:
import logging
(其中進口的logging
模塊),
import mylib
(其中進口你的庫mylib.py
),
def main():
(結合名稱main
給函數的編譯字節碼),和:
if __name__ == '__main__':
main()
(是運行在main
因爲本地名稱__name__
其實綁定到一個字符串比較等於字符串__main__
)。
到目前爲止,這可能不是很令人吃驚(除可能在導入myapp.py
時遇到的情況下運行)。
可能是的部分令人驚訝的是執行兩個import
語句期間發生的情況。
進口機械已發展了不少(並在Python3比Python2有所不同),但它在本質上確實這些不同的東西:
- 找到該文件(使用
sys.path
)
- 如果這是該文件的第一進口,運行所有的可執行語句文件
- 使用或修改
sys.modules
(見下文)
- 綁定生成的對象(S)(某事
<type 'module'>
或其中的一個名稱)添加到您提供的名稱(隱含地使用常規import
,明確使用from ... import ... as name
)。
這裏的一個關鍵項目是斜體部分。該模塊實際上在第一個import
上運行。成功導入的結果是一個模塊實例,其被添加到sys.modules
詞典:
$ python2
...
>>> import sys
>>> x = sys.modules['copy_reg']
>>> print x
<module 'copy_reg' from '/usr/local/lib/python2.7/copy_reg.pyc'>
如果在這一點上,你問蟒蛇重新導入的模塊,它會悄悄地做幾乎沒有:
>>> import copy_reg
>>>
這裏會發生什麼事是,Python的告示,該模塊已經加載和sys.modules
因此它只是提取已加載模塊實體(一個我們也勢必以上符號x
)。然後它將名稱copy_reg
綁定到這個已經存在的模塊。如果您import copy_reg as y
:
>>> import copy_reg as y
名字還綁定到符號y
:
>>> print x, y, copy_reg
<module 'copy_reg' from '/usr/local/lib/python2.7/copy_reg.pyc'> <module 'copy_reg' from '/usr/local/lib/python2.7/copy_reg.pyc'> <module 'copy_reg' from '/usr/local/lib/python2.7/copy_reg.pyc'>
地看到,這些其實都是相同模塊,我們可以使用id
功能,打印潛在對象的內部地址:
>>> print id(x), id(y), id(copy_reg)
34367067648 34367067648 34367067648
(差異nt run或不同版本的Python可能會在這裏產生一組不同的3位地址值,但所有這三個地址值都會匹配,因爲這些都是指相同的模塊)。
在任何情況下,在你main
在myapp
,符號logging
指同一logging
模塊中mylib
符號logging
。
在你的原代碼,調用(從do_something
在mylib
)logging.warning
在myapp
後您main
打印消息已經叫日誌配置代碼。日誌消息因此按照指示進行。
在你的編輯,你已經改變mylib
儘快的import mylib
聲明負荷myilb
無條件調用(通過do_something
)的logging.warning
函數來創建模塊。這發生在myapp
,之前結合main
到代碼和之前調用main
。所以即消息出來在控制檯上。
由日誌代碼決定是否服從(從後面)basicConfig
來自main
的呼叫。正如你可以從你自己的例子看到的那樣,它不會在打印消息之後嘗試重新定向根配置(這是因爲當時它設置了它的內部日誌處理程序,就像我記得的那樣)。
是的,但您然後從另一個模塊導入一個模塊並使用其功能。 – Ffisegydd
當我在mylib的末尾添加「do_something()」時,你如何解釋?py,日誌顯示在控制檯上,而不是日誌文件中? –