一、背景
最近在學pyhon的web框架Karrigell,下載了源碼之後運行,出現了error:
ImportError:No module named k_target
在www/index.py裏面importk_target,但是運行的時候出現了上述錯誤,網上查了一下,知道
是不同目錄下 import模塊或者包的話,需要將模塊或者包的路徑加入到sys.path中。於是使用了
sys.path.append('e:\Karrigell\karrigell\core')解決了問題。藉此機會又重新學習了一下python的
import機制和搜索路徑。
二、python的import機制
2.1 模塊和包
模塊化編程使得軟件開發更加靈活,不同的功能可多人協作完成,同時便於代碼複用和後期維護,
python使用import模塊/包來組織各個模塊,使不同模塊直接可以調用。
模塊:python中,每個py文件被稱之爲模塊,它可以定義變量,方法和類;
包:是一個目錄,它可以包含py文件和子目錄,最重要的一點是包一定含有一個__init__.py文件。
只要模塊或者包所在的目錄在sys.path中,就能使用import 來引用其他模塊內的變量,方法和類。
2.2 import的過程
1. Python中所有加載到內存的模塊都放在sys.modules。當import一個模塊時首先會在這個列表中
查找是否已經加載了此模塊,如果加載了則只是將模塊的名字加入到正在調用import的模塊的
Local名字空間中。如果沒有加載則從sys.path目錄中按照模塊名稱查找模塊文件,模塊文件可以
是py、pyc、pyd,找到後將模塊載入內存,並加入到sys.modules中,並將名稱導入到當前的
Local名字空間。若沒有找到,則import沒有效果,運行時出現ImportError:Nomodule named ***.
所以: import A
|
查看sys.moudles--->找到,導入模塊名字到當前模塊
|
沒有找到,則搜索sys.path--->找到,模塊加載到內存,加入sys.moudles
|
沒有找到,則import沒有效果
2.每個模塊在內存只有一份,即pyModuleObject對象只有一個,首次import該模塊時加載到內存,
然後存放在sys.modules裏,其他模塊再引用該模塊的時候,在sys.modules裏面可以直接找到。
2.3 包的import
前面已經講了只要有__init__.py,這個目錄都可以稱爲一個包。包下面的子目錄也可以是子包。
如果查看包的類型importSQLAlchemy type(SQLAlchemy),可以看到其實也是<type'module'>。
所以import包的時候,查找路徑也是sys.path,加載到內存後也會放在sys.modules中。
import包的時候,需要考慮__init__.py,因爲首次導入包的時候會執行此文件裏面的語句而不是
模塊裏面的語句,例如執行importpackage;就會執行__init__.py文件,如果想在導入包時做一些
初始化工作,eg:導入其他的包都可以寫在這個文件裏面。eg:列表__all__=["module1","module2"],
它包含了執行 from package import *時導入的模塊。
2.4 import的使用
如果想要引用某個模塊A.py中內容,有兩種方法:
1.import A; A.func()這實際上是把整個A的代碼在當前環境中執行了一遍,A模塊裏面的變量,
方法都可以被當前模塊引用
2.from A import func;func();這個是在當前環境中建立和變量func()同名的對象,並且將A中的
變量賦值給它,直接引用變量或者方法,但是你不能在當前模塊裏面定義同名的變量或者函數。
注意:import只能模塊,包,而不能直接import變量,函數,類。importA.func()就是錯的。
如果想要引用某個包B,也有幾種方法:
1.import B; 想要使用B包下面A模塊的func,B.A.func()-----這時,一定要在__init__裏進行一些
初始化設定,否則內存中只加載了B,並沒有加載模塊A,func()調用不到
2.import B.A ; B.A.func()
3.from B import A; A.func() from B import *,可以引用所有的模塊
4.from B.A import func; func()
5.from B import A as a1;爲A取了別名
2.5 import的嵌套
1. A模塊importB, B模塊importC,A中建立了一個local的名字空間B,A模塊只能訪問B中的變量
和函數,而不能訪問C的。如果想訪問C,只能importC。
2. A模塊importB,B模塊importA.參考:http://blog.csdn.net/sinat_16790541/article/details/43376741
三、模塊的搜索路徑
由前面我們知道import模塊的時候,如果模塊沒有在sys.modules裏面,即沒有加載進內存,
那麼會去sys.path裏面搜索模塊,這裏sys.path就是模塊的搜索路徑,如果看一個模塊能不能
import成功,就看它是否在sys.path裏面可以找到。
1. sys.path的第一個選項,是主模塊所以目錄,在交互環境下是一個空項,對應當前目錄。
2.在windows下,若設置了PYTHONPATH,那麼這裏設定的路徑會被自動添加到sys.path裏面,
所以可以自己添加PYTHONPATH
3.將自己想要import的模塊或者包的路徑添加到sys.path裏,sys.path.append("路徑名”)
-------但是這是暫時性的,只要重新運行python,這個路徑就消失了
4.將自己想要import的模塊或者包放到site_packages目錄下.
(from distutils.sysconfig import get_python_lib; printget_python_lib()顯示site-packages目錄)
5.使用pth文件,在site-packages文件中創建.pth文件,將模塊的路徑寫進去,一行一個路徑
6.將自己想要import的模塊添加到$python_dir/lib