[英]Import vendored dependencies in Python package without modifying sys.path or 3rd party packages
[英]Import a Third Party Python Project without Adding It to sys.path
我正在嘗試在我自己的代碼中導入第三方 python '項目'。 我沒有將它稱為 package,因為它似乎已准備好自行運行,而不是其他人將其導入並在其他地方運行。 例如,該第三方項目可能如下所示:
ProjectA/
|- utils/
|- tools.py
|- lib/
|- functions.py
|- main.py
文件/函數的依賴關系如下:
In main.py:
- from lib.functions import xxx
In lib/functions.py:
- from utils.tools import yyy
這樣
main.py
需要來自lib/functions.py
的 function xxx
,並且lib/functions.py
中運行 function xxx
需要 utils.tools.py 中的utils.tools.py
yyy
。 如果我在項目 A 的頂層運行main.py
,則lib
和utils
在此級別都是可見的,因此main.py
可以成功運行。 或者,如果我想在其他地方運行main.py
中的函數,我可以將path_to_ProjectA
添加到sys.path
並且一切運行良好。
但是,在某些情況下,我不想將此項目添加到sys.path
。 例如,我可能想使用另一個項目ProjectB
,它也有一個utils
子模塊,或者我自己的項目中已經有一個utils
子模塊。 在這些情況下,如果我將ProjectA
和ProjectB
都添加到sys.path
,那么只有一個utils
子模塊將被識別(即可以導入)。
因此,我想知道是否有方法可以使另一個項目可用於導入。 我能想到的是讓項目成為一個“合法”的package,例如,在每個級別添加__init__.py
,更改導入包/函數的方式等。(實際上,我沒有太多這樣做的經驗,而且我也不清楚如何做。)但是,我不認為這總是可行的,尤其是當該項目規模很大並且可能需要對項目結構的設計有公平的理解時。
總而言之,我的問題是,我應該怎么做才能在該項目之外導入第三方 python 項目而不將其添加到sys.path
,即使該項目可能設計為僅在其頂級目錄級別運行?
編輯 #1 (20220819)
在@Lenntror 的評論之后,我在這里添加了一個最小的示例。 目標是從ProjectA
ProjectA.lib.functions.xxx
將ProjectA
添加到sys.path
。
(a) 在
ProjectA.lib.functions.xxx
內部調用ProjectA
第三方ProjectA
的結構:
ProjectA/
|-- lib
| |-- __init__.py # Empty
| `-- functions.py
|-- utils
|-- __init__.py # Empty
`-- tools.py
`-- main.py
ProjectA/lib/functions.py
的內容:
from utils.tools import yyy
def xxx() :
print("This is xxx().")
print("Now xxx() calls yyy().")
yyy()
ProjectA/utils/tools.py
的內容:
def yyy() :
print("This is yyy().")
ProjectA/main.py
的內容:
from lib.functions import xxx
def main() :
print("This is main().")
print("Now calling xxx().")
xxx()
if __name__=='__main__' :
main()
如果我在ProjectA
目錄下運行python main.py
。 有用:
This is main().
Now calling xxx().
This is xxx().
Now xxx() calls yyy().
This is yyy().
(b) 通過將
ProjectA
添加到sys.path
,在ProjectA
之外調用ProjectA.lib.functions.xxx
假設,我有另一個文件夾MyProject
,它位於ProjectA
旁邊(和外部):
./
|-- MyProject
| `-- my_script.py
|
`-- ProjectA
|-- ...
MyProject/my_script.py
的內容:
import sys
sys.path.append("../ProjectA")
from lib.functions import xxx
def main() :
print("This is outside of ProjectA.")
print("Now calling xxx().")
xxx()
if __name__=='__main__' :
main()
這也成功運行:
This is outside of ProjectA.
Now calling xxx().
This is xxx().
Now xxx() calls yyy().
This is yyy().
(c) 通過在子目錄/模塊中包含
ProjectA
來調用ProjectA.lib.functions.xxx
現在,我在ProjectA
之外的另一個文件夾中有一個腳本。 這一次,我將ProjectA
包含在這個文件夾中,如下所示:
MyProject2/
|-- my_script.py
`-- thirdparty
`-- ProjectA
|-- ...
MyProject2/my_script.py
的內容:
from thirdparty.ProjectA.lib.functions import xxx
def main() :
print("This is outside of ProjectA.")
print("Now calling xxx().")
xxx()
if __name__=='__main__' :
main()
這給出了一個錯誤:
Traceback (most recent call last):
File "my_script.py", line 1, in <module>
from thirdparty.ProjectA.lib.functions import xxx
File "/workspace/MyProject2/thirdparty/ProjectA/lib/functions.py", line 1, in <module>
from utils.tools import yyy
ModuleNotFoundError: No module named 'utils'
所以你可以有這樣的項目文件:
ProjectA/
|- utils/
|- tools.py
|- lib/
|- functions.py
|- main.py
ProjectB/
|- utils/
|- tools.py
|- lib/
|- functions.py
|- main.py
your_project_file.py
your_project_file.py
、 ProjectA
和ProjectB
位於同一目錄中。
在your_project_file.py
中,您可以使用如下導入語句:
from ProjectA.lib.functions import xxx
但我認為您已經意識到這將導致utils.tool
問題。 您需要做的是使用相對路徑。 編輯lib/functions.py
文件並在utils.tool
前面放置一個點,它應該變成from.utils.tool import yyy
現在它應該可以解決您的問題,並且導入your_project_file.py
應該可以正常工作。 如果沒有,那么您需要為所有文件夾定義__init__.py
文件。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.