Python_base20181122_包,模組
什麼是包?
包本質上就是一個資料夾,只不過包比普通的資料夾多了一個__init__.py
檔案。
什麼是模組?
模組本質上就是一個py
檔案。
為什麼要引入包和模組?
引入函式是為了防止在同一個模組中多寫重複程式碼。
引入模組是為了防止在同一個包中多寫重複模組。
引入包是為了將模組分門別類的放好。
python中都有什麼樣的模組?
- python標準庫
- 第三方模組
- 自定義模組
import
or from... import ...
的執行流程:
別管是import
還是 from...import...
都會把相關的模組(.py
檔案)執行一遍。
可用的語法:
import 模組
from 模組 import 函式
import 包.模組
from 包 import 模組
from 包.模組 import 函式
__name__
的作用:
if __name__ == 'main':
# 倆作用。
如果呼叫者是它自己,則執行
如果它是被呼叫者,則不執行。
根據這個特性,可以當作測試程式碼。
也就是說,加了這個東西,如果包被呼叫的話,是不執行的。而且不影響你自己測試。
因為你自己測試的時候是可執行的。
當寫好的py
檔案被自己用時,__name__
的值是__main__
寫好的py
檔案被別人用時,__name__
的值是此py
檔案的路徑
注意:
調包的時候一定要注意,path
裡只把呼叫者的路徑加入了path
。作業系統只根據path
去找指定的模組或包。調包的時候是有優先順序的,優先順序最高的是time
,sys
等用C語言寫成的內建在了python
編譯器中的模組。然後再根據path
列表去找指定的模組或包。
包和模組的補充:
一般來說,我們的目錄結構是這樣的:
那麼,a.py
想呼叫c.py
,怎麼做?
根據之前的討論,執行a.py
時,作業系統會將xxxxxxx/dir1
加入環境變數。但是環境變數中並沒有dir2
這個目錄,所以根本沒辦法通過from dir2 import c
這樣來找。但是在pycharm
中這麼寫反而過了,為啥?
from dir2 import c # 在終端下這麼寫是不行的
# 在pycharm下這麼寫可以是因為pycharm把工程目錄module_test加入到了sys.path
import sys
print(sys.path)
因為pycharm
自作主張的把工程目錄加入到了sys.path
中,用終端執行一下就看出來了。
D:\pythonprogram\module_test\dir1>python a.py
['D:\\pythonprogram\\module_test\\dir1', 'C:\\Users\\bjfuvth\\AppData\\Local\\Programs\\Python\\Python37\\python37.zip', 'C:\\Users\\bjfuvth\\AppData\\Local\\Programs\\Python\\Python37\\DLLs', 'C:\\Users\\bjfuvth\\AppData\\Local\\Programs\\Python\\Python37\\lib', 'C:\\Users\\bjfuvth\\AppData\\Local\\Programs\\Python\\Python37', 'C:\\Users\\bjfuvth\\AppData\\Local\\Programs\\Python\\Python37\\lib\\site-packages']
終端下會提示找不到dir2
D:\pythonprogram\module_test\dir1>python a.py
Traceback (most recent call last):
File "a.py", line 1, in <module>
from dir2 import c
ModuleNotFoundError: No module named 'dir2'
另外pycharm
還幹了個好事兒。如果你想輸出__file__
.看名字是應該輸出檔名,但是在pycharm
下你會拿到這個檔案的絕對路徑。
程式碼:
print(__file__)
pycharm
的輸出:
D:/pythonprogram/module_test/dir1/a.py
終端的輸出:
a.py
所以說在操作這塊知識點的時候一定要注意pycharm
乾的兩件好事兒。
那麼問題來了?我們怎麼在剛剛所示的目錄結構中,寫出可移植性強的程式呢?如果對方裝的不是pycharm
呢?那就需要我們自己幹pycharm
幹過的好事兒了。
import os
import sys
ABS = os.path.abspath(__file__) # 拿到file的絕對路徑
print(ABS)
LASTABS = os.path.dirname(ABS)
print(LASTABS) # 這樣拿到file的目錄
LL = os.path.dirname(LASTABS) # 拿到file目錄的父級目錄
# file的目錄是到dir1 它的父級是module_test 這個目錄下就能找到dir2了
print(LL)
sys.path.append(LL) # 將module_test臨時加入環境變數
print(sys.path)
from dir2 import c
這樣在pycharm
下和終端下都可以執行了,可移植性賊好。
終端下執行結果:
D:\pythonprogram\module_test\dir1>python a.py
D:\pythonprogram\module_test\dir1\a.py
D:\pythonprogram\module_test\dir1
D:\pythonprogram\module_test
['D:\\pythonprogram\\module_test\\dir1', 'C:\\Users\\bjfuvth\\AppData\\Local\\Programs\\Python\\Python37\\python37.zip', 'C:\\Users\\bjfuvth\\AppData\\Local\\Programs\\Python\\Python37\\DLLs', 'C:\\Users\\bjfuvth\\AppData\\Local\\Programs\\Python\\Python37\\lib', 'C:\\Users\\bjfuvth\\AppData\\Local\\Programs\\Python\\Python37', 'C:\\Users\\bjfuvth\\AppData\\Local\\Programs\\Python\\Python37\\lib\\site-packages', 'D:\\pythonprogram\\module_test']
pycharm
下執行結果:
D:\pythonprogram\module_test\dir1\a.py
D:\pythonprogram\module_test\dir1
D:\pythonprogram\module_test
['D:\\pythonprogram\\module_test\\dir1', 'D:\\pythonprogram\\module_test', 'D:\\pythonprogram\\module_test\\venv\\Scripts\\python37.zip', 'C:\\Users\\bjfuvth\\AppData\\Local\\Programs\\Python\\Python37\\DLLs', 'C:\\Users\\bjfuvth\\AppData\\Local\\Programs\\Python\\Python37\\lib', 'C:\\Users\\bjfuvth\\AppData\\Local\\Programs\\Python\\Python37', 'D:\\pythonprogram\\module_test\\venv', 'D:\\pythonprogram\\module_test\\venv\\lib\\site-packages', 'D:\\pythonprogram\\module_test\\venv\\lib\\site-packages\\setuptools-39.1.0-py3.7.egg', 'D:\\pythonprogram\\module_test\\venv\\lib\\site-packages\\pip-10.0.1-py3.7.egg', 'D:\\Users\\bjfuvth\\AppData\\Roaming\\JetBrains\\PyCharm 2018.2.2\\helpers\\pycharm_matplotlib_backend', 'D:\\pythonprogram\\module_test']
補充一點,os.path.dirname()
不光可以獲取檔案的目錄,還能獲取目錄的目錄。
什麼叫目錄? 比如D:\pythonprogram\module_test\dir1\a.py
。。
D:\pythonprogram\module_test\dir1
就是 a.py
的目錄。