关于python导入模块和package的一些深度思考
背景
在python中有導(dǎo)入模塊和導(dǎo)入package一說,這篇文章主要介紹導(dǎo)入模塊和package的一些思考。
首先什么是模塊?什么是package?
模塊:用來從邏輯上組織python代碼(變量,函數(shù),類),本質(zhì)上就是以.py結(jié)尾的python文件
package:本質(zhì)上就是一個目錄,但是必須帶一個init.py的文件,它是用來從邏輯上組織模塊的
import的本質(zhì)是什么?
導(dǎo)入模塊的本質(zhì):就是把python文件拿來解釋一遍
導(dǎo)入包的本質(zhì):就是執(zhí)行該package下的init.py文件、
深入思考
導(dǎo)入模塊
如果我現(xiàn)在有一個這樣的目錄:
在bin文件目錄下的hello.py內(nèi)容是:
def hello():print('i am in bin dir')
在Day5文件目錄下的hello.py內(nèi)容是:
def hello():print('i am in Day5 dir')
在pythonFile文件目錄下的hello.py內(nèi)容是:
def hello():print('i am in pythonFile dir')
如果我現(xiàn)在在bin目錄下的test.py下寫入
import hello
hello.hello()
會出現(xiàn)的結(jié)果是什么呢?
大家很自然會想到是
i am in bin dir
是的確實(shí)是這樣的。但是為什么呢?
這個需要提及到環(huán)境變量的問題,我們可以看看當(dāng)前文件所處的環(huán)境變量到底里面有什么?
使用下面的語句:
import sys, os
print('--------')
for path in sys.path:print(path)
print('--------')
其中sys.path是所有環(huán)境變量的所構(gòu)成的列表,我們將里面的內(nèi)容分行打印。可以得到:
--------
D:\0 sty file\myCode\pythonFile\Day5\bin
D:\0 sty file\myCode\pythonFile
C:\ProgramData\Anaconda3\python36.zip
C:\ProgramData\Anaconda3\DLLs
C:\ProgramData\Anaconda3\lib
C:\ProgramData\Anaconda3
C:\ProgramData\Anaconda3\lib\site-packages
C:\ProgramData\Anaconda3\lib\site-packages\Babel-2.5.0-py3.6.egg
C:\ProgramData\Anaconda3\lib\site-packages\win32
C:\ProgramData\Anaconda3\lib\site-packages\win32\lib
C:\ProgramData\Anaconda3\lib\site-packages\Pythonwin
--------
這是我電腦里面的當(dāng)前文件運(yùn)行時候的環(huán)境變量。我們可以知道導(dǎo)入模塊和package時候,我們的程序會從這個sys.path中從前到后尋找這些目錄下有沒有我們要找的模塊,可以看見D:\0 sty file\myCode\pythonFile\Day5\bin是在第一個的所有我們直接導(dǎo)入hello模塊。python找到的D:\0 sty file\myCode\pythonFile\Day5\bin里面的hello.py找到之后,就不找了,然后打印出來了。
導(dǎo)入的問題來了
現(xiàn)在問題來了,我現(xiàn)在就想要導(dǎo)入D:\0 sty file\myCode\pythonFile\Day5下面的hello,那我應(yīng)該怎么辦?
我們知道在python中我們可以找到當(dāng)前文件所在目錄的父目錄,然后將他加入到運(yùn)行環(huán)境時候的環(huán)境變量中去,注意是運(yùn)行環(huán)境中的,因?yàn)樵诋?dāng)前python文件運(yùn)行結(jié)束后,這個環(huán)境變量就釋放了。
我們可以了解如下語句:
import sys, os # 導(dǎo)入系統(tǒng)模塊
print(os.path.abspath(__file__)) #打印當(dāng)前文件所處的絕對路徑
print(os.path.dirname(os.path.abspath(__file__))) #打印當(dāng)前文件所處的目錄
# 打印當(dāng)前文件所處的目錄的父目錄
print( os.path.dirname(os.path.dirname(os.path.abspath(__file__))))# Outputs:
# D:\0 sty file\myCode\pythonFile\Day5\bin\test.py
# D:\0 sty file\myCode\pythonFile\Day5\bin
# D:\0 sty file\myCode\pythonFile\Day5
然后我們就可以在寫下如下的代碼:
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.append(BASE_DIR) # 將BASE_DIR加入到系統(tǒng)環(huán)境變量
我們將當(dāng)前文件所在目錄的父目錄加入到環(huán)境變量中去,然后我們在打印下sys.path得到:
--------
D:\0 sty file\myCode\pythonFile\Day5\bin
D:\0 sty file\myCode\pythonFile
C:\ProgramData\Anaconda3\python36.zip
C:\ProgramData\Anaconda3\DLLs
C:\ProgramData\Anaconda3\lib
C:\ProgramData\Anaconda3
C:\ProgramData\Anaconda3\lib\site-packages
C:\ProgramData\Anaconda3\lib\site-packages\Babel-2.5.0-py3.6.egg
C:\ProgramData\Anaconda3\lib\site-packages\win32
C:\ProgramData\Anaconda3\lib\site-packages\win32\lib
C:\ProgramData\Anaconda3\lib\site-packages\Pythonwin
D:\0 sty file\myCode\pythonFile\Day5
--------
我們可以看出D:\0 sty file\myCode\pythonFile\Day5加到了sys.path的最后一個,現(xiàn)在我們將之前的開頭的寫的
import hello
hello.hello()
一定要注釋,一定要注釋,一定要注釋,因?yàn)槿绻蝗サ舻脑?#xff0c;這個hello.hello()方法就已經(jīng)存放在內(nèi)存里面了,不管你后面如何去該環(huán)境變量,python會始終去找到內(nèi)存中直接有的hello()方法。
我們將這行代碼加到test.py的最后面,運(yùn)行得到結(jié)果是:
i am in bin dir
這是為什么呢,原因還是那個sys.path中個路徑順序的問題,如果我們要讓我們設(shè)置的BASE_DIR 中的模塊首先導(dǎo)入我們就需要用列表中的insert()方法2而不是‘a(chǎn)ppend()’的了,這就避免了再環(huán)境變量中已經(jīng)有的路徑有同名的模塊。
我們改為:
sys.path.insert(0, BASE_DIR)
發(fā)現(xiàn)輸出的結(jié)果就是
i am in Day5 dir
完整代碼如下:
# import hello #使用添加環(huán)境變量后的模塊一定要注釋到
# hello.hello()import sys, os
print('--------')
for path in sys.path:print(path)
print('--------')BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
#sys.path.append(BASE_DIR)
sys.path.insert(0, BASE_DIR)print('--------')
for path in sys.path:print(path)
print('--------')import hello
hello.hello()
最后提一下:
如果我們要使用pythonFile下的hello中hello(),道理還是一樣的,大家自己去實(shí)現(xiàn)吧。
導(dǎo)入package
導(dǎo)入package時候設(shè)置環(huán)境變量的問題和導(dǎo)入模塊是一樣的,就不贅述了,但是需要注意的一點(diǎn)是導(dǎo)入package后,package下的init.py里的內(nèi)容是自動執(zhí)行的。
如我在test_package下的init.py中寫入
print('i am in test_package __init__')
當(dāng)我們在
import test_package
后就自動執(zhí)行了,這在我們管理很多文件時候,進(jìn)行初始化的作用相當(dāng)好用啊。
轉(zhuǎn)載請注明出處:
CSDN:樓上小宇_home:http://blog.csdn.net/sty945
簡書:樓上小宇:http://www.jianshu.com/u/1621b29625df
總結(jié)
以上是生活随笔為你收集整理的关于python导入模块和package的一些深度思考的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 关于二叉树的层次遍历的花样(c++实现)
- 下一篇: 102. Binary Tree Lev