在上一篇《老男人開始學(xué)python之Flask中的“Hello World”》中,雖然只按照教程寫了幾行短短的代碼背零,但是對于初學(xué)者的我來說就產(chǎn)生了一些疑問腰吟,有一些不明白的地方?
- 為什么文件名是“
__init__.py
”? - “
__name__
”是什么? - from ... import ... 是什么意思毛雇?
- form ... import ... 和 import ...的區(qū)別是什么嫉称?
帶著問題去看了Python基礎(chǔ)教程模塊一節(jié)記錄總結(jié)一下。
參考教程:
廖雪峰:模塊灵疮、使用模塊织阅、安裝第三方模塊
鏈接:http://www.liaoxuefeng.com/
一、什么是模塊震捣、包荔棉、庫?
| Module(模塊)| Package(包)| Library(庫)|
| --------------------- | :------------------ | --------------- -: |
| 一個(gè).py
文件就稱之為一個(gè)模塊(Module)| 只要包含__init__.py
文件的文件夾就叫做包| 參考其他編程語言的說法蒿赢。就是指Python中完成一定功能的代碼集合润樱,供用戶使用的代碼組合。在python中是包和模塊的形式 | | abc.py模塊名就是abc诉植;|1.
init.py文件必須存在祥国,否則就是一個(gè)文件夾;2.
init.py文件可以為空晾腔,也可以有python代碼舌稀;3. 可以有多級層次結(jié)構(gòu)包含多個(gè)模塊或子包組成;4.
init.py`文件本身就是一個(gè)模塊灼擂,模塊名就是包含它的文件夾的名稱壁查; |例如常說的第三方庫,是否可以簡單理解為包含多個(gè)Package(包)完成某功能的一個(gè)代碼集合 |
1.Package 包中都可以包含什么剔应?
F:\pythontest\test2.py # test2模塊
F:\pythontest\test3 # test3文件夾中包含__init__.py文件睡腿,因此是一個(gè)包;
│ a.py # test3.a模塊峻贮;
│ b.py # test3.b模塊席怪;
│ __init__.py # 也是一個(gè)模塊,名稱是:test3
│
├─b # 包含2個(gè)模塊的一個(gè)【文件夾】纤控,但是名稱和test3.b名稱同名了挂捻,該【文件夾】下的模塊能正常使用嗎?如果這里是個(gè)同名的子包呢船万?
│ a.py
│ b.py
│
├─c # 一個(gè)空【文件夾】
├─d # 因?yàn)榘琠_init__.py文件刻撒,因此是一個(gè)子包
│ a.py # 模塊名:test3.d.a
│ b.py # 模塊名:test3.d.a
│ __init__.py # 模塊名:test3.d
│
└─e # 包含2個(gè)模塊的一個(gè)【文件夾】,該文件夾下的2個(gè)模塊能用嗎耿导?
a.py # 暫認(rèn)為模塊名為:test3.e.a
b.py # 暫認(rèn)為模塊名為:test3.e.b
如上所示声怔,一個(gè)包中可以包含:模塊(a、b)舱呻、包含模塊的文件夾(b醋火、e)、空文件夾(c)、子包(d)胎撇。
【說明】到了這里解決了第1個(gè)問題介粘,為什么文件名是“__init__.py
”,因?yàn)樗且粋€(gè)Package(包)晚树;
下邊做一些測試:
#F:\pythontest\test3\a.py代碼如下:
def a():
return "my name is 'a'"
#F:\pythontest\test3\b.py代碼如下:
def b():
return "my name is 'b'"
#F:\pythontest\test3\b\a.py代碼如下:
def a():
return "我是B文件夾下的 'a'"
#F:\pythontest\test3\b\b.py代碼如下:
def b():
return "我是B文件夾下的 'b'"
#F:\pythontest\test3\d\a.py代碼如下:
def a():
return "我是D子包中的 'a'"
#F:\pythontest\test3\d\b.py代碼如下:
def b():
return "我是D子包中的 'b'"
__init__.py
文件全部為空姻采,F:\pythontest\test2.py
文件中代碼分別為如下幾種情況的執(zhí)行結(jié)果:
-----------------------------------------------------------------------------------
import test3
x = test3.a.a()
print (x)
#執(zhí)行結(jié)果:
F:\pythontest>flask\Scripts\python.exe test2.py
Traceback (most recent call last):
File "test2.py", line 2, in <module>
x = test3.a.a()
AttributeError: 'module' object has no attribute 'a'
【總結(jié)】:因?yàn)閷?dǎo)入的模塊名為test3,也就是test3文件夾下的`__init__.py `文件爵憎,而該文件為空慨亲,所以找不到test3.a模塊中的a函數(shù);
-----------------------------------------------------------------------------------
使用import test3.a 導(dǎo)入test3.a模塊宝鼓,即test3文件夾下的a.py文件刑棵,就可以正常執(zhí)行:
import test3.a
x = test3.a.a()
print (x)
#執(zhí)行結(jié)果:
F:\pythontest>flask\Scripts\python.exe test2.py
my name is 'a'
-----------------------------------------------------------------------------------
#代碼如下:
import test3.b
x = test3.b.b()
print (x)
#執(zhí)行結(jié)果:
F:\pythontest>flask\Scripts\python.exe test2.py
my name is 'b'
#代碼更改如下:測試導(dǎo)入b文件夾中的b模塊
import test3.b.b
x = test3.b.b.b()
print (x)
#執(zhí)行結(jié)果:沒有模塊test3.b.b,test3.b不是一個(gè)包愚铡;
F:\pythontest>flask\Scripts\python.exe test2.py
Traceback (most recent call last):
File "<frozen importlib._bootstrap>", line 2218, in _find_and_load_unlocked
AttributeError: 'module' object has no attribute '__path__'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "test2.py", line 1, in <module>
import test3.b.b
ImportError: No module named 'test3.b.b'; 'test3.b' is not a package
-----------------------------------------------------------------------------------
如果給b文件夾下放一個(gè)空__init__.py文件蛉签,這時(shí)候b文件夾就成了test3的一個(gè)子包則:
import test3.b
x = test3.b.b()
print (x)
#執(zhí)行結(jié)果:
F:\pythontest>flask\Scripts\python.exe test2.py
Traceback (most recent call last):
File "test2.py", line 2, in <module>
x = test3.b.b()
AttributeError: 'module' object has no attribute 'b'
【總結(jié)】因?yàn)閷?dǎo)入test3.b模塊的時(shí)候?qū)嶋H上b子包把test3.b模塊覆蓋了,實(shí)際上導(dǎo)入的是b文件夾中的__init__.py文件沥寥,而該文件為空碍舍,因此找不到b函數(shù);
#更改代碼如下:導(dǎo)入test3.b模塊邑雅,即test3\b\__init__.py
import test3.b
x = test3.b.a.a()
print (x)
#同時(shí)修改test3\b\__init__.py文件代碼如下:
import test3.b.a
#執(zhí)行結(jié)果:
F:\pythontest>flask\Scripts\python.exe test2.py
我是B文件夾下的 'a'
這個(gè)時(shí)候就是test3\b\__init__.py文件中導(dǎo)入了test3.b.a模塊片橡,然后在test2.py文件中導(dǎo)入了test3.b模塊即test3\b\__init__.py文件,換句話說就是在test3\b\__init__.py文件中引入了test3\b\a.py文件淮野,然后在test2.py文件中又引入了test3\b\__init__.py文件捧书,因此a.py中的a函數(shù)能被正常執(zhí)行。
-----------------------------------------------------------------------------------
#最后來看看e文件夾中的模塊文件能否被正常導(dǎo)入并使用模塊中的函數(shù)骤星?
代碼如下:
import test3.e.a
x = test3.e.a.a()
print (x)
#執(zhí)行結(jié)果:
F:\pythontest>flask\Scripts\python.exe test2.py
我是E文件夾下的 'a'模塊
從執(zhí)行結(jié)果來看经瓷,是可以正常運(yùn)行的。
更改一下代碼:
import test3.e
x = test3.e.a.a()
print (x)
執(zhí)行結(jié)果:
F:\pythontest>flask\Scripts\python.exe test2.py
Traceback (most recent call last):
File "test2.py", line 2, in <module>
x = test3.e.a.a()
AttributeError: 'module' object has no attribute 'a'
從以上兩例測試洞难,可以看到雖然e只是個(gè)文件夾不是子包舆吮,但是該文件夾下的模塊文件依然可以被導(dǎo)入。
上邊的兩個(gè)問題:
- 含2個(gè)模塊的一個(gè)【文件夾】廊营,但是名稱和test3.b名稱同名了歪泳,該【文件夾】下的模塊能正常使用嗎萝勤?如果這里是個(gè)同名的子包呢露筒?
如果在test3包中,含有一個(gè)b.py和一個(gè)b文件夾敌卓,則b.py文件(模塊)可以被導(dǎo)入慎式,而b文件夾中的.py文件不能被導(dǎo)入;
如果b文件夾是一個(gè)子包,則子包覆蓋b.py瘪吏;
【注意】不要重名癣防,以免混淆! - 文件夾e掌眠,不是子包蕾盯,該文件下包含2個(gè).py文件(模塊),該文件夾下的2個(gè)模塊能用嗎蓝丙?
可以被導(dǎo)入使用级遭。這是為什么呢?
二渺尘、如何使用Module(模塊)挫鸽?
import 命令為導(dǎo)入Module(模塊)命令,而Module指的就是一個(gè).py文件鸥跟,其實(shí)就可以認(rèn)為是在一個(gè).py文件中引入另外一個(gè).py文件丢郊。
1. 使用導(dǎo)入Module(模塊)命令import
有幾種格式:
命令 | 解釋 |
---|---|
import module | 導(dǎo)入單個(gè)模塊 |
import module as name | 導(dǎo)入單個(gè)模塊并重命名 |
import moudule1, moudule2,module3,... | 一次導(dǎo)入多個(gè)模塊 |
import moudule1 as name1,module2 as name2,... | 一次導(dǎo)入多個(gè)模塊并重命名 |
一般在文件首部導(dǎo)入所有模塊,推薦順序如下:
python標(biāo)準(zhǔn)庫
第三方模塊
應(yīng)用程序自定義模塊
2. 使用from...import...語句導(dǎo)入模塊的屬性(變量医咨、函數(shù)枫匾、對象)
命令 | 解釋 |
---|---|
from module import name1,name2,name3 | 單行導(dǎo)入 |
from module import name1,name2,\ name3 | 多行導(dǎo)入 |
from module import * | 導(dǎo)入全部屬性,一般不推薦使用腋逆,適合模塊中變量名很長和很多的情況婿牍。容易覆蓋當(dāng)前命名空間中現(xiàn)有的名字 |
當(dāng)試圖加載一個(gè)模塊的時(shí)候,Python會在指定的路徑下搜索對應(yīng)的.py文件惩歉,如果找不到等脂,就會報(bào)錯(cuò)。
默認(rèn)情況下,Python解釋器會搜索當(dāng)前文件夾、所有已安裝的內(nèi)置模塊和第三方模塊耳贬,搜索路徑存放在sys模塊的path變量中呐萌。
有兩種方法修改搜索路徑:
一是直接修改sys.path,添加要搜索的文件夾:sys.path.append('路徑')
第二種方法是設(shè)置環(huán)境變量PYTHONPATH曹货,該環(huán)境變量的內(nèi)容會被自動(dòng)添加到模塊搜索路徑中。設(shè)置方式與設(shè)置Path環(huán)境變量類似。注意只需要添加你自己的搜索路徑模软,Python自己本身的搜索路徑不受影響。
模塊被導(dǎo)入時(shí)饮潦,加載的時(shí)候模塊頂層代碼會被執(zhí)行燃异,一個(gè)模塊無論被導(dǎo)入多少次,只加載一次继蜡,可以防止多次導(dǎo)入時(shí)代碼被多次執(zhí)行回俐。
內(nèi)建函數(shù)reload可以重新導(dǎo)入一個(gè)已經(jīng)存在的模塊逛腿。
三、 “__name__
”是什么仅颇?
簡單的說:
1.如果模塊(就是一個(gè).py)文件是直接執(zhí)行的单默,則__name__
值就等于__main__
;
2.如果模塊是被導(dǎo)入的時(shí)候忘瓦,__name__
的值就是模塊名搁廓;
#test_name2.py 代碼為:
def test_name2(): # 定義一個(gè)函數(shù)test_name2
b = __name__ # 將__name__賦值給變量b
return b # 函數(shù)返回變量b的值
if __name__ == "__main__": # 如果__name__ 等于字符串__main__ 就可以認(rèn)為是直接執(zhí)行的test_name2.py文件,則打印test_name2()函數(shù)的返回值耕皮;
print (test_name2())
#test_name1.py 代碼為:
import test_name2 # 導(dǎo)入模塊 test_name2
print (test_name2.test_name2()) # 打印test_name2模塊中的test_name2函數(shù)值枚抵;
直接執(zhí)行test_name2的結(jié)果:結(jié)果為__main__
F:\pythontest>flask\Scripts\python.exe test_name2.py
__main__
直接執(zhí)行test_name1的結(jié)果:結(jié)果為模塊名
F:\pythontest>flask\Scripts\python.exe test_name1.py
test_name2
可做調(diào)試代碼用;
參考:
python:淺析python 中name = 'main' 的作用
python中name的使用