助于理解 Python if __name__ == '__main__' 的小案例

參考資料:

StackOverFlow解釋

代碼studymodule_1

# -*- coding=utf-8 -*-
""" studymodule_1 """
print(__name__)

def sum(a=0,b=1): #設(shè)定默認(rèn)值,調(diào)用函數(shù)時,如果沒有傳遞參數(shù)狸驳,則會使用默認(rèn)參數(shù)值
    print("sum() in studymodule_1.py")  # 功能
    return a+b


print("top-level in studymodule_1.py") #全局

"""" __name__是一個全局變量沦童,在模塊內(nèi)部是用來標(biāo)識模塊的名稱的"""
if __name__ == '__main__':
    import sys
    print(sys.argv[0])
    a = int(input("輸入數(shù)字a"))
    b = int(input("輸入數(shù)字b"))
    print(sum(a,b))
    print("studymodule_1.py is being run directly")

else:
    print("studymodule_1.py is being imported into another module")

代碼studymodule_2

# -*- coding=utf-8 -*-
""" studymodule_2 """
print(__name__)

import studymodule_1

print("top-level in studymodule_2.py") #全局

c = studymodule_1.sum() #沒有指定參數(shù),使用附帶默認(rèn)值

"""" __name__是一個全局變量,在模塊內(nèi)部是用來標(biāo)識模塊的名稱的"""
if __name__ == '__main__':
    import sys
    print("studymodule_2.py is being run directly")
    print("計算機(jī)結(jié)果是{}".format(c))
else:
    print("studymodule_2.py is being imported into another module")

如果你執(zhí)行studymodule_1.py文件 (放在python site-packages中)

python studymodule_1.py

會提示輸入并輸出:

__main__
top-level in studymodule_1.py 
C:\python\Lib\site-packages\studymodule_1.py
輸入數(shù)字a
輸入數(shù)字b
sum() in studymodule_1.py
a+b之和
studymodule_1.py is being run directly
image.png

如果你執(zhí)行studymodule_2.py文件

python studymodule_2.py

會提示輸入并輸出:

__main__
studymodule_1
top-level in studymodule_1.py
studymodule_1.py is being imported into another module
top-level in studymodule_2.py
sum() in studymodule_1.py
studymodule_2.py is being run directly
計算機(jī)結(jié)果是1 (函數(shù)默認(rèn)參數(shù))
image.png

StackOverFlow上比較精彩的解釋 :

Thus, when module one gets loaded, its name equals "one" instead of main

參考資料

下面是更深入的理解

程序入口

對于很多編程語言來說由捎,程序都必須要有一個入口适掰,比如 C叉袍,C++,以及完全面向?qū)ο蟮木幊陶Z言 Java叨橱,C# 等典蜕。如果你接觸過這些語言,對于程序入口這個概念應(yīng)該很好理解罗洗,C 和 C++ 都需要有一個 main 函數(shù)來作為程序的入口愉舔,也就是程序的運行會從 main 函數(shù)開始。同樣伙菜,Java 和 C# 必須要有一個包含 Main 方法的主類來作為程序入口轩缤。

而 Python 則有不同,它屬于腳本語言贩绕,不像編譯型語言那樣先將程序編譯成二進(jìn)制再運行火的,而是動態(tài)的逐行解釋運行。也就是從腳本第一行開始運行淑倾,沒有統(tǒng)一的入口馏鹤。

一個 Python 源碼文件除了可以被直接運行外,還可以作為模塊(也就是庫)被導(dǎo)入娇哆。不管是導(dǎo)入還是直接運行湃累,最頂層的代碼都會被運行(Python 用縮進(jìn)來區(qū)分代碼層次)勃救。而實際上在導(dǎo)入的時候,有一部分代碼我們是不希望被運行的治力。

舉一個例子來說明一下蒙秒,假設(shè)我們有一個 const.py 文件,內(nèi)容如下:

PI = 3.14

def main():
    print "PI:", PI

main()

我們在這個文件里邊定義了一些常量宵统,然后又寫了一個 main 函數(shù)來輸出定義的常量晕讲,最后運行 main 函數(shù)就相當(dāng)于對定義做一遍人工檢查,看看值設(shè)置的都對不對马澈。然后我們直接執(zhí)行該文件(python const.py),輸出:

PI: 3.14

現(xiàn)在瓢省,我們有一個 area.py 文件,用于計算圓的面積箭券,該文件里邊需要用到 const.py 文件中的 PI 變量净捅,那么我們從 const.py 中把 PI 變量導(dǎo)入到 area.py 中:

from const import PI

def calc_round_area(radius):
    return PI * (radius ** 2)

def main():
    print "round area: ", calc_round_area(2)

main()

運行 area.py疑枯,輸出結(jié)果:

PI: 3.14
round area:  12.56

可以看到辩块,const 中的 main 函數(shù)也被運行了,實際上我們是不希望它被運行荆永,提供 main 也只是為了對常量定義進(jìn)行下測試废亭。這時,if name == 'main' 就派上了用場具钥。把 const.py 改一下:

PI = 3.14

def main():
    print "PI:", PI

if __name__ == "__main__":
    main()

然后再運行 area.py豆村,輸出如下:

round area:  12.56

再運行下 const.py,輸出如下:

PI: 3.14

這才是我們想要的效果骂删。

if __name__ == '__main__'

就相當(dāng)于是 Python 模擬的程序入口掌动。Python 本身并沒有規(guī)定這么寫,這只是一種編碼習(xí)慣宁玫。由于模塊之間相互引用粗恢,不同模塊可能都有這樣的定義,而入口程序只能有一個欧瘪。到底哪個入口程序被選中眷射,這取決于 __ name __的值。

__ Name __

__ name __是內(nèi)置變量佛掖,用于表示當(dāng)前模塊的名字妖碉,同時還能反映一個包的結(jié)構(gòu)。來舉個例子芥被,假設(shè)有如下一個包:

a
├── b
│   ├── c.py
│   └── __init__.py
└── __init__.py

目錄中所有 py 文件的內(nèi)容都為:

print __name__

我們執(zhí)行 python -c "import a.b.c"欧宜,輸出結(jié)果:

http://blog.konghy.cn/2017/04/24/python-entry-program/

a
a.b
a.b.c

由此可見,__ name __ 可以清晰的反映一個模塊在包中的層次拴魄。其實冗茸,所謂模塊名就是 import 時需要用到的名字猛拴,例如:

import tornado
import tornado.web

這里的 tornado 和 tornado.web 就被稱為模塊的模塊名。

如果一個模塊被直接運行蚀狰,則其沒有包結(jié)構(gòu)愉昆,其 __ name __ 值為 __ main __。例如在上例中麻蹋,我們直接運行 c.py 文件(python a/b/c.py)跛溉,輸出結(jié)果如下:

__main__

所以,if __ name __ == '__ main __' 我們簡單的理解就是: 如果模塊是被直接運行的扮授,則代碼塊被運行芳室,如果模塊是被導(dǎo)入的,則代碼塊不被運行刹勃。

實際上堪侯,這個問題還可以衍生出其他的一些知識點,例如 __ main __.py 文件與 Python 的 -m 參數(shù)荔仁。

__ main __.py 文件與 python -m

Python 的 -m 參數(shù)用于將一個模塊或者包作為一個腳本運行伍宦,而 __ main __.py 文件則相當(dāng)于是一個包的”入口程序“。

首先我們需要來看看 python xxx.py 與 python -m xxx.py 的區(qū)別乏梁。兩種運行 Python 程序的方式的不同點在于次洼,一種是直接運行,一種是當(dāng)做模塊來運行遇骑。

先來看一個簡單的例子卖毁,假設(shè)有一個 Python 文件 run.py,其內(nèi)容如下:

import sys
print sys.path

我們用直接運行的方式啟動(python run.py)落萎,輸出結(jié)果(為了說明問題亥啦,輸出結(jié)果只截取了重要部分,下同):

['/home/huoty/aboutme/pythonstudy/main', ...]

然后以模塊的方式運行(python -m run.py):

['', ...]
/usr/bin/python: No module named run.py

由于輸出結(jié)果只列出了關(guān)鍵的部分练链,應(yīng)該很容易看出他們之間的差異翔脱。直接運行是把 run.py 文件所在的目錄放到了 sys.path 屬性中。以模塊方式運行是把你輸入命令的目錄(也就是當(dāng)前工作路徑)兑宇,放到了 sys.path 屬性中碍侦。以模塊方式運行還有一個不同的地方是,多出了一行 No module named run.py 的錯誤隶糕。實際上以模塊方式運行時瓷产,Python 先對 run.py 執(zhí)行一遍 import,所以 print sys.path 被成功執(zhí)行枚驻,然后 Python 才嘗試運行 run.py 模塊濒旦,但是,在 path 變量中并沒有 run.py 這個模塊再登,所以報錯尔邓。而正確的運行方式晾剖,應(yīng)該是 python -m run.

這個例子并不能明顯的說明問題。接著我們來看看 __ main __.py 的作用梯嗽。

仍然先看例子齿尽,有如下一個包:

package
├── __init__.py
└── __main__.py

__ init __.py

import sys
print "__init__"
print sys.path

__ main __.py

import sys
print "__main__"
print sys.path

用 python -m package 運行結(jié)果:

__init__
['', ...]
__main__
['', ...]

用 python package 運行結(jié)果:

__main__
['package', ...]

然后我們來總結(jié)一下:
1、 加上 -m 參數(shù)時會把當(dāng)前工作目錄添加到 sys.path 中灯节,而不加時則會把腳本所在目錄添加到 sys.path 中循头。
2、 加上 -m 參數(shù)時 Python 會先將模塊或者包導(dǎo)入炎疆,然后再執(zhí)行
3卡骂、 __ main__.py 文件是一個包或者目錄的入口程序。不管是用 python package 還是用 python -m package 運行時形入,__ main__.py 文件總是被執(zhí)行全跨。

后序

我試圖使用長篇大論來闡述,在 Python 中如何理解 if name == 'main' 這個問題亿遂,不知道我有沒有描述得足夠的明白浓若。Python 的確是簡單的,優(yōu)雅的崩掘,但也有很多問題是不太容易理解的七嫌,例如很多高級的特性,像元類苞慢、生成器表達(dá)式、描述符英妓、協(xié)程等挽放。Python 并沒有在太多的地方規(guī)定要如何如何,很多的用法只是慣用法蔓纠,例如 self 和本文討論的內(nèi)容辑畦。這些用法或是為了讓代碼看起來更優(yōu)雅,或是前人的經(jīng)驗腿倚。使用 Python 是有無限可能的纯出,你可以寫出很多簡潔優(yōu)雅的代碼。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末敷燎,一起剝皮案震驚了整個濱河市暂筝,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌硬贯,老刑警劉巖焕襟,帶你破解...
    沈念sama閱讀 206,378評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異饭豹,居然都是意外死亡鸵赖,警方通過查閱死者的電腦和手機(jī)务漩,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,356評論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來它褪,“玉大人饵骨,你說我怎么就攤上這事∶4颍” “怎么了宏悦?”我有些...
    開封第一講書人閱讀 152,702評論 0 342
  • 文/不壞的土叔 我叫張陵,是天一觀的道長包吝。 經(jīng)常有香客問我饼煞,道長,這世上最難降的妖魔是什么诗越? 我笑而不...
    開封第一講書人閱讀 55,259評論 1 279
  • 正文 為了忘掉前任砖瞧,我火速辦了婚禮,結(jié)果婚禮上嚷狞,老公的妹妹穿的比我還像新娘块促。我一直安慰自己,他們只是感情好床未,可當(dāng)我...
    茶點故事閱讀 64,263評論 5 371
  • 文/花漫 我一把揭開白布竭翠。 她就那樣靜靜地躺著,像睡著了一般薇搁。 火紅的嫁衣襯著肌膚如雪斋扰。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,036評論 1 285
  • 那天啃洋,我揣著相機(jī)與錄音传货,去河邊找鬼。 笑死宏娄,一個胖子當(dāng)著我的面吹牛问裕,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播孵坚,決...
    沈念sama閱讀 38,349評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼粮宛,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了卖宠?” 一聲冷哼從身側(cè)響起巍杈,我...
    開封第一講書人閱讀 36,979評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎逗堵,沒想到半個月后秉氧,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,469評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡蜒秤,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,938評論 2 323
  • 正文 我和宋清朗相戀三年汁咏,在試婚紗的時候發(fā)現(xiàn)自己被綠了亚斋。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,059評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡攘滩,死狀恐怖帅刊,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情漂问,我是刑警寧澤赖瞒,帶...
    沈念sama閱讀 33,703評論 4 323
  • 正文 年R本政府宣布,位于F島的核電站蚤假,受9級特大地震影響栏饮,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜磷仰,卻給世界環(huán)境...
    茶點故事閱讀 39,257評論 3 307
  • 文/蒙蒙 一袍嬉、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧灶平,春花似錦伺通、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,262評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至瞒爬,卻和暖如春弓柱,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背疮鲫。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評論 1 262
  • 我被黑心中介騙來泰國打工吆你, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人俊犯。 一個月前我還...
    沈念sama閱讀 45,501評論 2 354
  • 正文 我出身青樓,卻偏偏與公主長得像伤哺,于是被迫代替她去往敵國和親燕侠。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,792評論 2 345

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

  • 首先立莉,python不像java绢彤、C那樣,有內(nèi)置好的“main函數(shù)”這樣的程序入口蜓耻。 一般的python程序都是...
    _沉夢昂志閱讀 214評論 1 0
  • 原文地址推薦看原文茫舶,有代碼格式。擔(dān)心哪天作者刪掉后刹淌,沒有備份饶氏,才原樣復(fù)制如下存檔讥耗。 這個問題來自于知乎用戶的提問疹启,...
    貳條閱讀 516評論 0 1
  • 原文鏈接:http://blog.konghy.cn/2017/04/24/python-entry-progra...
    五秋木閱讀 353評論 0 0
  • 妮寶,今天是你參加英文決賽的日子喊崖,確切地說四年級應(yīng)該是昨天,但我們卻忘記了荤懂,幸好還有兩個同你一樣漏考的考生一起茁裙,得...
    恩企媽媽閱讀 247評論 0 0
  • 對节仿,我就是一只可愛的廉價拔草機(jī) 1. 啟初,超市買的粟耻,三十多特別便宜查近,柜姐誘惑我買一送一挤忙,但是我是那種貪便宜的人嗎...
    劉可以a閱讀 176評論 0 0