轉(zhuǎn)載至:https://cloud.tencent.com/developer/article/1175296
模塊:
在Python中,一個.py文件就稱之為一個模塊(Module)。
它是實現(xiàn)了某個功能的代碼集合。
模塊分為三種:
1.自定義模塊
2.內(nèi)置標準模塊(又稱標準庫)
3.開源模塊
模塊導入方法:
1. import module_name (導入一個模塊)
2. import module_name,module2_name (導入多個模塊)
3. from module_name import * (不推薦使用)
4. from module_name import m1 as name_m1 (導入指定的函數(shù)或變量并重命名)
5. from module_name import m1,m2,m3 (導入模塊的多個函數(shù)或變量)
第3種辦法,不推薦使用。因為這一段話,相當于把module_name.py的所有代碼復制到當前代碼中,調(diào)用的時候,直接寫方法名調(diào)用,不需要module_name.方法名()這種方式調(diào)用。如果發(fā)現(xiàn)方法名或者變量沖突,以本代碼為準。
import的本質(zhì)
把導入模塊的所有代碼解釋一遍,統(tǒng)一賦值給一個變量,這個變量名叫模塊名。
調(diào)用變量,使用 module_name.變量名
調(diào)用函數(shù),使用 module_name.函數(shù)名()
from的本質(zhì)
把導入模塊的指定函數(shù)或者變量,放到當前文件的位置,執(zhí)行一遍。
調(diào)用變量或者函數(shù)的時候,直接使用即可,不需要在前面加模塊名。
自定義一個模塊
新建文件hello.py,新建文件test.py,導入模塊。注意,模塊名是去除.py之后的名字
name = "zhang"
def say_hello():
print("hello,",name)
import hello
#輸出變量,執(zhí)行方法
print(hello.name)
hello.say_hello()
執(zhí)行輸出
zhang
hello, zhang
包:
用來從邏輯上組織模塊,本質(zhì)就是一個目錄(必須帶有一個init.py文件)
導入包的本質(zhì):
去執(zhí)行包目錄下的init.py文件
使用pycharm編輯器,新建一個包package_test
編輯init.py文件
print('from the package package_test')
新建一個文件p_test.py
import package_test
目錄結(jié)構(gòu)如下:
.
├── p_test.py
└── package_test
└── init.py
執(zhí)行p_test.py,輸出
from the package package_test
上面介紹的模塊導入,都是基于同級目錄的。那么module在不同目錄下,該如何導入呢?
目錄結(jié)構(gòu)如下:
.
├── hello.py
└── package_test
├── init.py
└── main.py
main.py需要導入hello模塊
先來分析一個導入模塊的執(zhí)行步驟
import module_name->找到module_name.py文件->找到module_name.py的路徑->sys.path(搜索路徑)
編輯main.py,打印sys.path
import sys
print(sys.path)
使用cmd執(zhí)行,執(zhí)行輸出
['E:\python_script\day5\package_test', 'C:\Program Files\Python36\python36.zip', 'C:\Program Files\Python36\DLLs', 'C:\Program Files\Python36\lib', 'C:\
\Program Files\Python36', 'C:\Program Files\Python36\lib\site-packages']
第一個元素,就是當前路徑
如果一個元素找不到,就會找下一個元素,直到所有的目錄都還找不到的話,就報錯
ModuleNotFoundError: No module named 'xxx'
為了解決這個問題,需要加一個路徑,必須要包含需要導入模塊的路徑。這個路徑,一般為項目根目錄。
編輯main.py,先來打印當前文件的絕對路徑
import sys,os
print(os.path.abspath(file))
執(zhí)行輸出
E:\python_script\day5\package_test\main.py
然后獲取當前目錄
import sys,os
print(os.path.dirname(os.path.abspath(file)))
執(zhí)行輸出
E:\python_script\day5\package_test
最后獲取上一層目錄,定義變量
import sys,os
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(file)))
print(BASE_DIR)
執(zhí)行輸出
E:\python_script\day5
這個目錄,就可以找到package_test路徑了!
將項目根目錄添加到系統(tǒng)環(huán)境變量中
import sys,os
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(file)))
sys.path.append(BASE_DIR)
最后導入模塊,執(zhí)行函數(shù)
import sys,os
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(file)))
sys.path.append(BASE_DIR)
import hello
hello.say_hello()
執(zhí)行輸出
hello, zhang
注意:
sys.path.append(BASE_DIR) 是將項目根目錄追加到最后一個列表元素。如果中間某一個元素,正好找到了指定文件,比如hello.py,那么就不會再查找后面的路徑了,直接加載。
如果出現(xiàn)了這種情況,必須要把BASE_DIR插入到第一個元素位置,使用insert方法
sys.path.insert(0,BASE_DIR)
print(sys.path)
執(zhí)行輸出
['E:\python_script\day5', 'E:\python_script\day5\package_test', 'E:\python_script', 'C:\Program Files\Python36\python36.zip', 'C:\Program Files\Python36\DLLs', 'C:\Program Files\Python36\lib', 'C:\Program Files\Python36', 'C:\Program Files\Python36\lib\site-packages']
舉另外一個例子
main.py需要調(diào)用test1.py里面的函數(shù),目錄結(jié)果如下:
.
├── module_test
│ └── main.py
└── package_test
├── init.py
└── test1.py
test1.py內(nèi)容如下:
def test():
print('in the test1')
main.py直接引用package_test包,是否可以執(zhí)行呢?
import sys,os
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(file)))
sys.path.append(BASE_DIR)
import package_test
package_test.test1.test()
執(zhí)行報錯
ModuleNotFoundError: No module named 'test1'
因為import package_test 這一步是執(zhí)行package_test目錄下的init.py文件,而這個文件是空的
修改init.py文件,從當前目錄下,導入test1模塊
這個 點 表示相對于init.py文件的路徑。
from . import test1
再次執(zhí)行main.py
執(zhí)行輸出
in the test1
再深層次的目錄調(diào)用,目錄結(jié)果如下:
python_script/
├── day4
│ └── test.py
└── day5
└── package_test
├── init.py
└── test1.py
day5的代碼,同上,沒改動
test.py需要調(diào)用test1.py,那么需要把python_script目錄加到環(huán)境變量即可
修改day4下的test.py文件
import sys,os
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(file)))
print(BASE_DIR)
執(zhí)行輸出
E:\python_script
加載到環(huán)境變量
import sys,os
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(file)))
sys.path.append(BASE_DIR)
from day5 import package_test
package_test.test1.test()
執(zhí)行輸出
in the test1
注意下面這行代碼
from day5 import package_test
day5表示python_script目錄下的day5
導入優(yōu)化
語法:
from 模塊名 import 函數(shù)或變量名
舉個例子,目錄結(jié)構(gòu)如下:
test4/
├── module_test.py
└── test.py
module_test.py內(nèi)容如下:
def test():
print('in the test')
test.py內(nèi)容如下:
import module_test
def logger():
module_test.test()
print('in the logger')
def search():
module_test.test()
print('in the search')
假設(shè)有N個函數(shù)在調(diào)用module_test.test()
...
logger()
執(zhí)行輸出
in the test
in the logger
module_test.test()在執(zhí)行的時候,先找到module_test模塊,再從里面檢索test函數(shù)是否存在。
那么每執(zhí)行一次,就要先找模塊,再找函數(shù),重復勞動,效率很低。
為了解決這個問題,就是在導入模塊的時候,不讓它找就可以了
import module_test
改成
from module_test import test
就可以了。
下面的執(zhí)行方法module_test.test()改成test() 就可以了,完整代碼如下
!/usr/bin/env python
coding: utf-8
author = 'www.py3study.com'
from module_test import test
def logger():
test()
print('in the logger')
def search():
test()
print('in the search')
....
logger()
執(zhí)行輸出
in the test
in the logger
這種方法,可以使代碼執(zhí)行的更快
為了避免函數(shù)重名,可以在導入的時候,起別名
from module_test import test as mod_test