![](/img/trans.png)
[英]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.