溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶(hù)服務(wù)條款》

深入淺析Python中的路徑

發(fā)布時(shí)間:2020-11-05 17:38:53 來(lái)源:億速云 閱讀:140 作者:Leah 欄目:開(kāi)發(fā)技術(shù)

這期內(nèi)容當(dāng)中小編將會(huì)給大家?guī)?lái)有關(guān)深入淺析Python中的路徑,文章內(nèi)容豐富且以專(zhuān)業(yè)的角度為大家分析和敘述,閱讀完這篇文章希望大家可以有所收獲。

1. 絕對(duì)路徑引入

Python 在搜索模塊時(shí),依次搜索sys.path里的位置,直到找到模塊為止。下面命令可以查看當(dāng)前的搜索路徑:

import sys
print(sys.path)

sys.path的初始值來(lái)源于兩個(gè)(其實(shí)還有一些更復(fù)雜但不常用的)。一個(gè)是系統(tǒng)的PYTHONPATH變量,因此可通過(guò)設(shè)置該變量,來(lái)設(shè)置 Python 默認(rèn)的搜索位置。比如:

export PYTHONPATH=/opt/python:$PYTHONPATH
echo $PYTHONPATH

將該命令放在系統(tǒng)初始化腳本(/etc/environment)或者 BASH 初始化腳本(/~/.bashrc)里,可以對(duì)每個(gè)新開(kāi)的窗口有效。

sys.path的另一個(gè)來(lái)源是當(dāng)前執(zhí)行程序所在的目錄 (而不是當(dāng)前目錄)。比如當(dāng)前目錄下文件夾./cc下有一個(gè)b.py,那么執(zhí)行./cc/b.py時(shí),./cc(而不是./?。⒈患拥絪ys.path:

python ./cc/b.py

2. 相對(duì)路徑引用

上面說(shuō)的是搜索模塊都是指絕對(duì)路徑引用。對(duì)于非系統(tǒng)目錄,就需要操縱sys.path。但操縱sys.path有外溢效果,因?yàn)樗且粋€(gè)全局變量。對(duì)于同一個(gè)庫(kù)里的模塊的互相引用,可以考慮使用相對(duì)路徑:

from . import abc
from .abc import fool
from ..up import foo

Note that both explicit and implicit relative imports are based on the name of the current module. Since the name of the main module is always __main__, modules intended for use as the main module of a Python application should always use absolute imports.

包含相對(duì)路徑 import 的 python 腳本不能直接運(yùn)行,只能作為 module 被引用。原因正如手冊(cè)中描述的,所謂相對(duì)路徑其實(shí)就是相對(duì)于當(dāng)前 module 的路徑,但如果直接執(zhí)行腳本,這個(gè) module 的 name 就是__main__, 而不是 module 原來(lái)的 name , 這樣相對(duì)路徑也就不是原來(lái)的相對(duì)路徑了,導(dǎo)入就會(huì)失敗。

在使用相對(duì)引用的文件中,不能有 __main__ 方法,只執(zhí)行作為一個(gè) module 進(jìn)行引用,而不是直接執(zhí)行腳本。

舉個(gè)簡(jiǎn)單例子。假設(shè)./cc/目錄下已有一個(gè)./cc/b.py(內(nèi)容為空)。當(dāng)前目錄下的./a.py內(nèi)容為:

from .cc import b

那么直接運(yùn)行python ./a.py將會(huì)報(bào)錯(cuò):

ModuleNotFoundError: No module named '__main__.cc'; '__main__' is not a package

另一個(gè)是常見(jiàn)的錯(cuò)誤是: ValueError: attempted relative import beyond top-level package。

在涉及到相對(duì)導(dǎo)入時(shí),package所對(duì)應(yīng)的文件夾必須正確的被python解釋器視作package,而不是普通文件夾。否則由于不被視作package,無(wú)法利用package之間的嵌套關(guān)系實(shí)現(xiàn)python中包的相對(duì)導(dǎo)入。

  文件夾被python解釋器視作package需要滿(mǎn)足兩個(gè)條件:

  1、文件夾中必須有__init__.py文件,該文件可以為空,但必須存在該文件。

  2、不能作為頂層模塊來(lái)執(zhí)行該文件夾中的py文件(即不能作為主函數(shù)的入口)。

  補(bǔ)充:在"from YY import XX"這樣的代碼中,無(wú)論是XX還是YY,只要被python解釋器視作package,就會(huì)首先調(diào)用該package的__init__.py文件。如果都是package,則調(diào)用順序是YY,XX。

  另外,練習(xí)中“from . import XXX”和“from .. import XXX”中的'.'和'..',可以等同于linux里的shell中'.'和'..'的作用,表示當(dāng)前工作目錄的package和上一級(jí)的package。

  舉個(gè)例子:

  testIm/

  --__init__.py

  --main.py : from Tom import tom

  --Tom/

    --__init__.py : print("I'm Tom's __init__!")

    --tom.py : from . import tomBrother, from .. import kate,print("I'm Tom!")

    --tomBrother.py print(I'm Tom's Brother!)

  --Kate/

    --__init__.py : print("I'm Kate's __init__!")

    --kate.py

  運(yùn)行文件:main.py

  結(jié)果:

I'm Tom's __init__!
I'm Tom's Brother!
Traceback (most recent call last):
File "D:\PythonLearning\TestIm\main.py", line 3, in <module>
from Tom import tom
File "D:\PythonLearning\TestIm\Kate\kate.py", line 4, in <module>
from .. import kate
ValueError: attempted relative import beyond top-level package
>>>

可以看到from . import tomBrother順利執(zhí)行,首先執(zhí)行了Tom文件夾下的__init__.py文件,后來(lái)執(zhí)行了tomBrother.py文件,但是當(dāng)執(zhí)行到“from .. import kate”時(shí)報(bào)錯(cuò),這是因?yàn)槲覀兪窃赥estIm文件夾下把main.py文件作為主函數(shù)的入口執(zhí)行的,因此盡管TestIm文件夾中有__init__.py文件,但是該文件夾不能被python解釋器視作package,即Tom package不存在上層packge,自然會(huì)報(bào)錯(cuò),相對(duì)導(dǎo)入時(shí)超出了最高層級(jí)的package。

修改方法:

  test/

  --main.py : from testIm.Tom import tom

  --testIm/

    --__init__.py

    --Tom/

      --__init__.py : print("I'm Tom's __init__!")

      --tom.py : from . import tomBrother, from .. import Kate,print("I'm Tom!")

      --tomBrother.py print(I'm Tom's Brother!)

    --Kate/

    --__init__.py : print("I'm Kate's __init__!")

    --kate.py

  運(yùn)行文件:main.py

結(jié)果:  

I'm top's __init__!
I'm Tom's __init__!
I'm Tom's Brother!!
I'm Kate's __init__!
I'm Tom!

即主函數(shù)入口不在TestIm中,則TestIm和其同樣包含__init__.py文件的子文件夾都被python解釋器視作package,形成相應(yīng)的嵌套關(guān)系??梢哉J褂胒rom . import XXX和from .. import XXX。

上述就是小編為大家分享的深入淺析Python中的路徑了,如果剛好有類(lèi)似的疑惑,不妨參照上述分析進(jìn)行理解。如果想知道更多相關(guān)知識(shí),歡迎關(guān)注億速云行業(yè)資訊頻道。

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI