1. 程式人生 > >Python_base20181122_包,模組

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的目錄。