詳解Python中的路徑問題
1. 絕對路徑引入
Python 在搜索模塊時,依次搜索sys.path里的位置,直到找到模塊為止。下面命令可以查看當前的搜索路徑:
import sysprint(sys.path)
sys.path的初始值來源于兩個(其實還有一些更復雜但不常用的)。一個是系統的PYTHONPATH變量,因此可通過設置該變量,來設置 Python 默認的搜索位置。比如:
export PYTHONPATH=/opt/python:$PYTHONPATHecho $PYTHONPATH
將該命令放在系統初始化腳本(/etc/environment)或者 BASH 初始化腳本(/~/.bashrc)里,可以對每個新開的窗口有效。
sys.path的另一個來源是當前執行程序所在的目錄 (而不是當前目錄)。比如當前目錄下文件夾./cc下有一個b.py,那么執行./cc/b.py時,./cc(而不是./?。⒈患拥絪ys.path:
python ./cc/b.py
2. 相對路徑引用
上面說的是搜索模塊都是指絕對路徑引用。對于非系統目錄,就需要操縱sys.path。但操縱sys.path有外溢效果,因為它是一個全局變量。對于同一個庫里的模塊的互相引用,可以考慮使用相對路徑:
from . import abcfrom .abc import foolfrom ..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.
包含相對路徑 import 的 python 腳本不能直接運行,只能作為 module 被引用。原因正如手冊中描述的,所謂相對路徑其實就是相對于當前 module 的路徑,但如果直接執行腳本,這個 module 的 name 就是__main__, 而不是 module 原來的 name , 這樣相對路徑也就不是原來的相對路徑了,導入就會失敗。
在使用相對引用的文件中,不能有 __main__ 方法,只執行作為一個 module 進行引用,而不是直接執行腳本。
舉個簡單例子。假設./cc/目錄下已有一個./cc/b.py(內容為空)。當前目錄下的./a.py內容為:
from .cc import b
那么直接運行python ./a.py將會報錯:
ModuleNotFoundError: No module named ’__main__.cc’; ’__main__’ is not a package
另一個是常見的錯誤是: ValueError: attempted relative import beyond top-level package。
在涉及到相對導入時,package所對應的文件夾必須正確的被python解釋器視作package,而不是普通文件夾。否則由于不被視作package,無法利用package之間的嵌套關系實現python中包的相對導入。
文件夾被python解釋器視作package需要滿足兩個條件:
1、文件夾中必須有__init__.py文件,該文件可以為空,但必須存在該文件。
2、不能作為頂層模塊來執行該文件夾中的py文件(即不能作為主函數的入口)。
補充:在'from YY import XX'這樣的代碼中,無論是XX還是YY,只要被python解釋器視作package,就會首先調用該package的__init__.py文件。如果都是package,則調用順序是YY,XX。
另外,練習中“from . import XXX”和“from .. import XXX”中的’.’和’..’,可以等同于linux里的shell中’.’和’..’的作用,表示當前工作目錄的package和上一級的package。
舉個例子:
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
運行文件:main.py
結果:
I’m Tom’s __init__!I’m Tom’s Brother!Traceback (most recent call last):File 'D:PythonLearningTestImmain.py', line 3, in <module>from Tom import tomFile 'D:PythonLearningTestImKatekate.py', line 4, in <module>from .. import kateValueError: attempted relative import beyond top-level package>>>
可以看到from . import tomBrother順利執行,首先執行了Tom文件夾下的__init__.py文件,后來執行了tomBrother.py文件,但是當執行到“from .. import kate”時報錯,這是因為我們是在TestIm文件夾下把main.py文件作為主函數的入口執行的,因此盡管TestIm文件夾中有__init__.py文件,但是該文件夾不能被python解釋器視作package,即Tom package不存在上層packge,自然會報錯,相對導入時超出了最高層級的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
運行文件:main.py
結果:
I’m top’s __init__!I’m Tom’s __init__!I’m Tom’s Brother!!I’m Kate’s __init__!I’m Tom!
即主函數入口不在TestIm中,則TestIm和其同樣包含__init__.py文件的子文件夾都被python解釋器視作package,形成相應的嵌套關系??梢哉J褂胒rom . import XXX和from .. import XXX。
以上就是詳解Python中的路徑問題的詳細內容,更多關于Python 路徑的資料請關注好吧啦網其它相關文章!
相關文章: