python中import 模块的路径问题
對于系統的包我們導入沒有疑問
但是如果我們自己寫的文件夾里面的python文件呢?
自己寫的文件import時候會出現路徑問題的疑惑
比如同目錄下面的python文件被import 時候
和 其他目錄下面的python文件被import時候
根據當前的python文件是否為執行文件
import的python文件的路徑就是有區別的
1.先看看python如何定位到模塊文件的
使用 imoort a 或者 from a import func
使用這種import 的時候是如何定位到模塊 a的呢?
直接使用 import sys 的時候又是如何定位到sys這個模塊的呢?
這個學過python的都知道因為搜索路徑存在。默認先在當前目錄下搜索,
然后是python的安裝目錄下的文件
1.sys.path提供了搜索路徑
如果 import sys
使用 sys.path 是可以看到有一些目錄的
python按照這個目錄順序進行搜索。
2.文件的__name__提供了模塊名字
每一個Python對象有這個__name__屬性
如果當前的python為執行文件,此處簡稱為驅動文件,那么__name__的值就是__main__
可以理解為main函數
如果當前python不是執行文件,只是我們組織模塊用的,那么__name__就是該文件的相對路徑
3.python文件的定位就是 sys.path 和 __name__指定的路徑的拼接
2.看看自己寫的文件import的問題
下面做個試驗看看這個自己寫的文件import的問題
下面是做試驗用的文件目錄
folder1 目錄下 存放 a.py 和 b.py
folder2 目錄下 存放 c.py 和d.py?
每個文件里面簡單寫幾行代碼:
#a.py def f1():print("this is function f1 in a.py")print("a的__name__屬性是:"+__name__) #b.py def f2():print("this is function f2 in b.py")print("b的__name__屬性是:"+__name__) #c.py def f3():print("this is function f3 in c.py")print("c的__name__屬性是:"+__name__) #d.py def f4():print("this is function f4 in d.py")print("d的__name__屬性是:"+__name__)試驗1:同目錄下的文件import --- a.py 為執行文件
在a.py 里面引入 文件b.py , 并且此時 a.py 為驅動文件,可以執行下a.py 看看結果
from b import f2#a.py def f1():print("this is function f1 in a.py")f2() print("a的__name__屬性是:"+__name__)上面使用??
from b import f2
這種很好理解,可以定位到模塊 b
試驗2:同目錄下的文件import --- a.py 不執行
本次不執行 a.py , 我們弄一個demo.py 來作為驅動文件
然后在 demo.py 里面來 import a?
注意下,此時 demo.py 引入 a.py 時候使用的是?
from folder1.a這里帶著路徑 folder1.a
# demo.py from folder1.a import f1, f2 import sysf1() f2() print(__name__)然后運行下 demo.py:
居然報錯了
?有疑惑吧
剛才試驗1 里面直接執行 a.py 沒有錯誤啊
同樣的代碼,試驗2中在demo.py里面執行,就錯了,找不到模塊 b 了
為什么呢?
試驗3:在試驗2基礎上修改下a.py里面引入模塊b 的路徑
修改下? a.py
把 from b 修改為 from .b?
加了一個.?
from .b import f2#a.py def f1():print("this is function f1 in a.py")f2() print("a的__name__屬性是:"+__name__)然后再運行下demo.py:
?疑問:
為什么此時需要修改下 a.py 里面 模塊b的imoport 路徑才可以運行通過??
簡單分析下:
對比下試驗1 和試驗2 其實還有區別的,
a.py 作為驅動文件和不作為驅動文件,還有驅動文件的目錄發生了變化
試驗1中:
a.py作為驅動文件,那么搜索路徑就是當前文件夾? ?import理解/folder1
也就是搜索路徑
那么b.py被引用,那么它的__name__就是 b? (相對路徑)
所以 2個組合起來是可以找到 b 的
試驗2中:
此時demo.py作為驅動文件,那么當前目錄?import理解/ 就是搜索路徑
此時demo.py要找到 模塊a , a被imort之后 ,那么a的__name__就是相對路徑 folder1.a
根據前面所說搜索路徑就是 sys.path 和當前模塊__name__路徑的拼接
所以demo.py加載 a 的時候實際上的搜索路徑是? ?import理解/folder1
加載a的時候,首先要去加載b
當前的搜索路徑是??import理解/folder1
此時b被引用,所以 b的__name__是? folder1.b
繼續拼接
可以看到 2個 如果直接組合在一起的話:?import理解/folder1/folder1/b
有 2個? folder1的 這個路徑是錯誤的
所以? 試驗2中? from b import f2? 此時就無法找到 模塊b 了
如何正確找到呢?
那么就需要修改下 import 的模塊路徑了
使用 from .b 之后 表示了加載當前目錄下面的模塊 b
當前目錄就是? /import理解/folder1? ,從而可以找到
如果 from 后面不加模塊路徑,那就是直接按照 上面的路徑拼接進行查找的
試驗4:import 不同目錄的文件--a.py作為驅動文件
先在 a.py 里面使用 folder2下面的 c
此時把 a.py作為驅動文件進行試驗,所以先把?from .b import f2 得改回來?
from b import f2 from folder2.c import f3 #a.py def f1():print("this is function f1 in a.py")f2() f3() print("a的__name__屬性是:"+__name__)?此時會報錯誤,找不到模塊
根據前面結論 sys.path+模塊__name__指定路徑拼接
此時的搜索路徑為:
import理解/folder1
模塊c被引用,此時它的__name__是 folder2.c
那么拼接起來肯定無法在 folder1目錄下來找到 folder2的
此刻有人想不是相對路徑么,既然當前在 folder1下面,那么..就是上級目錄
所以使用? ?
from ..folder2.c import f3 試試結果還是報錯的
?ValueError: attempted relative import beyond top-level package
說明 ..是行不通的? 不能使用..作為相對目錄去尋找
那該怎么辦呢??
只要能保證搜索路徑能找到這個模塊那就能import的
因此如果c.py的目錄也在這個搜索路徑里面就是可以的
試驗5:sys.path 來定位路徑
基于上面的試驗4代碼,當前問題是搜索路徑為??import理解/folder1
如何去尋找??import理解/folder2呢?
既然搜索路徑是通過這個 sys.path來進行的
那么修改這個 sys.path呢?
比如我們把上層目錄加入到 sys.path里面看看
sys.path.append("../") from b import f2 import sys sys.path.append("../") from folder2.c import f3 #a.py def f1():print("this is function f1 in a.py")f2() f3() print("a的__name__屬性是:"+__name__)果然出來了
所以可以通過修改 sys.path 的值增加搜索路徑解決問題
此時使用sys.path 是可以使用 ..表示上層目錄的
通過上面的試驗可以看到搜索路徑的理解很重要
試驗6 :?import 不同目錄的文件--a.py 不執行
本次不借助sys.path的修改
此時的 a.py 如果不執行呢?
此時 先把 from b 要改回? from .b
下面這段代碼使用? demo.py來作為驅動文件執行
from .b import f2 from folder2.c import f3 #a.py def f1():print("this is function f1 in a.py")f2() f3() print("a的__name__屬性是:"+__name__)此時再次驅動 demo.py執行
# demo.py from folder1.a import f1, f2 import sysf1() f2() print(__name__)?可以看到 此時 a.py 中 使用??
from folder2.c import f3這個是可以正常加載的
原因就是因為 當前搜索路徑變為了?import理解/
從而尋找模塊c 的時候 import理解/foleder2 是可以正常找到的
可見,這個搜索路徑多么重要
而且驅動文件所在的目錄也很重要
最好把它放到頂層根目錄下面
試驗7:如果使用 import b 不是 from b 這種呢
繼續使用demo.py作為驅動
然后我們在? a.py 里面 使用 import b的方式去加載 b
運行demo.py:
結果顯而易見,肯定找不到 b 的
此時必須使用
import folder1.b from .b import f2 from folder2.c import f3 import folder1.b #a.py def f1():print("this is function f1 in a.py")f2() f3() print("a的__name__屬性是:"+__name__)很明細使用import b 這種方式
就是直接的把搜索路徑和當前的模塊名字路徑拼接起來的進行查找
總結
通過上面的試驗可以看到,能否找到我們自己寫的模塊文件
搜索路徑很重要的
而且還跟當前的 文件是否為 驅動文件有直接關系
如上面的 a.py
它作為驅動文件 時候 就可以直接 import b
但是如果是demo.py作為驅動文件的時候,a.py 里面必須是?
import folder1.b都是因為當前搜索路徑搗的鬼
方法
1.可以使用 sys.path里面增加路徑的方式
? ?指定一些路徑加入到里面,這樣就可以搜索到我們自己寫的文件
2.將驅動文件放到最頂層,比如這里的 demo.py
? ?然后從最頂層的目錄為基準,里面寫的文件的路徑都是相對于它的
??
3.使用包
如果我們使用包,那么把包都部署在lib下面這樣lib本身在 sys.path 里面的
這樣像 系統包 那樣的使用方式使用,這樣不用擔心相對路徑的問題了
不管那種寫法,還是要明白搜索路徑是如何找到文件模塊的
總結
以上是生活随笔為你收集整理的python中import 模块的路径问题的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: drupal mysql hash密码_
- 下一篇: sis最新ip地址2020入口一_【新版