[英]Import a Third Party Python Project without Adding It to sys.path
I am trying to import a third party python 'project' in my own code.我正在尝试在我自己的代码中导入第三方 python '项目'。 I am not referring it as a package because it seems to be prepared for running on its own but not for others to import it and run it somewhere else.
我没有将它称为 package,因为它似乎已准备好自行运行,而不是其他人将其导入并在其他地方运行。 For example, that third party project may look like this:
例如,该第三方项目可能如下所示:
ProjectA/
|- utils/
|- tools.py
|- lib/
|- functions.py
|- main.py
and the dependency of files/functions goes like:文件/函数的依赖关系如下:
In main.py:
- from lib.functions import xxx
In lib/functions.py:
- from utils.tools import yyy
such that这样
main.py
requires the function xxx
from lib/functions.py
, andmain.py
需要来自lib/functions.py
的 function xxx
,并且xxx
in lib/functions.py
requires the function yyy
in utils.tools.py
.lib/functions.py
中运行 function xxx
需要 utils.tools.py 中的utils.tools.py
yyy
。 If I run main.py
at the top level of Project A, both lib
and utils
are visible at this level so main.py
runs successfully.如果我在项目 A 的顶层运行
main.py
,则lib
和utils
在此级别都是可见的,因此main.py
可以成功运行。 Or, if I want to run the functions inside main.py
somewhere else, I can add path_to_ProjectA
to sys.path
and everything runs well too.或者,如果我想在其他地方运行
main.py
中的函数,我可以将path_to_ProjectA
添加到sys.path
并且一切运行良好。
However, there are occasions in which I prefer not to add this project to sys.path
.但是,在某些情况下,我不想将此项目添加到
sys.path
。 For example, I might want to use another project ProjectB
which also has a utils
submodule, or I already have a utils
submodule in my own project.例如,我可能想使用另一个项目
ProjectB
,它也有一个utils
子模块,或者我自己的项目中已经有一个utils
子模块。 In these cases, if I add both ProjectA
and ProjectB
to sys.path
, then only one of utils
submodules will get recognized (ie, can be imported).在这些情况下,如果我将
ProjectA
和ProjectB
都添加到sys.path
,那么只有一个utils
子模块将被识别(即可以导入)。
Therefore, I am wondering if there would be methods to make another's project available for importing.因此,我想知道是否有方法可以使另一个项目可用于导入。 What I can think of is to make the project a 'legit' package, eg, adding
__init__.py
at each level, changing the way to import packages/functions, etc. (Actually, I do not have much experience in doing this, and I do not have a clear idea about how too.) However, I do not believe this is always practical, especially when that project is sizeable and it may require fair understanding to the design of the project structure.我能想到的是让项目成为一个“合法”的package,例如,在每个级别添加
__init__.py
,更改导入包/函数的方式等。(实际上,我没有太多这样做的经验,而且我也不清楚如何做。)但是,我不认为这总是可行的,尤其是当该项目规模很大并且可能需要对项目结构的设计有公平的理解时。
To summarize, my question is, what should I do so that I can import a third party python project outside that project without adding it to sys.path
, even though that project is probably designed to be run only at its top directory level?总而言之,我的问题是,我应该怎么做才能在该项目之外导入第三方 python 项目而不将其添加到
sys.path
,即使该项目可能设计为仅在其顶级目录级别运行?
Edit #1 (20220819)编辑 #1 (20220819)
Following @Lenntror 's comments, I am adding a minimal example here.在@Lenntror 的评论之后,我在这里添加了一个最小的示例。 The goal is to call
ProjectA.lib.functions.xxx
from the outside of ProjectA
without adding ProjectA
to sys.path
.目标是从
ProjectA
ProjectA.lib.functions.xxx
将ProjectA
添加到sys.path
。
(a) Calling
ProjectA.lib.functions.xxx
insideProjectA
(a) 在
ProjectA.lib.functions.xxx
内部调用ProjectA
Structure of the third-party ProjectA
:第三方
ProjectA
的结构:
ProjectA/
|-- lib
| |-- __init__.py # Empty
| `-- functions.py
|-- utils
|-- __init__.py # Empty
`-- tools.py
`-- main.py
Content of ProjectA/lib/functions.py
: ProjectA/lib/functions.py
的内容:
from utils.tools import yyy
def xxx() :
print("This is xxx().")
print("Now xxx() calls yyy().")
yyy()
Content of ProjectA/utils/tools.py
: ProjectA/utils/tools.py
的内容:
def yyy() :
print("This is yyy().")
Content of ProjectA/main.py
: ProjectA/main.py
的内容:
from lib.functions import xxx
def main() :
print("This is main().")
print("Now calling xxx().")
xxx()
if __name__=='__main__' :
main()
If I run python main.py
under the directory ProjectA
.如果我在
ProjectA
目录下运行python main.py
。 It works:有用:
This is main().
Now calling xxx().
This is xxx().
Now xxx() calls yyy().
This is yyy().
(b) Calling
ProjectA.lib.functions.xxx
outsideProjectA
by addingProjectA
tosys.path
(b) 通过将
ProjectA
添加到sys.path
,在ProjectA
之外调用ProjectA.lib.functions.xxx
Let's say, I have another folder MyProject
which is next to (and outside) ProjectA
:假设,我有另一个文件夹
MyProject
,它位于ProjectA
旁边(和外部):
./
|-- MyProject
| `-- my_script.py
|
`-- ProjectA
|-- ...
Content of MyProject/my_script.py
: 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 also runs successfully:这也成功运行:
This is outside of ProjectA.
Now calling xxx().
This is xxx().
Now xxx() calls yyy().
This is yyy().
(c) Calling
ProjectA.lib.functions.xxx
by includingProjectA
in a sub-directory/module(c) 通过在子目录/模块中包含
ProjectA
来调用ProjectA.lib.functions.xxx
Now, I have a script in another folder also outside of ProjectA
.现在,我在
ProjectA
之外的另一个文件夹中有一个脚本。 This time, I include ProjectA
inside this folder like this:这一次,我将
ProjectA
包含在这个文件夹中,如下所示:
MyProject2/
|-- my_script.py
`-- thirdparty
`-- ProjectA
|-- ...
Content of MyProject2/my_script.py
: 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()
This gives an error:这给出了一个错误:
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'
So you could have the project file as this:所以你可以有这样的项目文件:
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
and ProjectB
are sitting inside the same directory. your_project_file.py
、 ProjectA
和ProjectB
位于同一目录中。
inside your_project_file.py
you could use import statements like this:在
your_project_file.py
中,您可以使用如下导入语句:
from ProjectA.lib.functions import xxx
But I think you figured this out already that this will cause issue from utils.tool
.但我认为您已经意识到这将导致
utils.tool
问题。 What you need to do, is use relative path.您需要做的是使用相对路径。 Edit
lib/functions.py
file and place a dot in front of utils.tool
which should become from.utils.tool import yyy
编辑
lib/functions.py
文件并在utils.tool
前面放置一个点,它应该变成from.utils.tool import yyy
Now it should resolve your problem and import in your_project_file.py
should work fine.现在它应该可以解决您的问题,并且导入
your_project_file.py
应该可以正常工作。 If not, then you need to define __init__.py
file for all folders.如果没有,那么您需要为所有文件夹定义
__init__.py
文件。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.