繁体   English   中英

导入第三方 Python 项目而不将其添加到 sys.path

[英]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

这样

  1. 运行main.py需要来自lib/functions.py的 function xxx ,并且
  2. lib/functions.py中运行 function xxx需要 utils.tools.py 中的utils.tools.py yyy

如果我在项目 A 的顶层运行main.py ,则libutils在此级别都是可见的,因此main.py可以成功运行。 或者,如果我想在其他地方运行main.py中的函数,我可以将path_to_ProjectA添加到sys.path并且一切运行良好。

但是,在某些情况下,我不想将此项目添加到sys.path 例如,我可能想使用另一个项目ProjectB ,它也有一个utils子模块,或者我自己的项目中已经有一个utils子模块。 在这些情况下,如果我将ProjectAProjectB都添加到sys.path ,那么只有一个utils子模块将被识别(即可以导入)。

因此,我想知道是否有方法可以使另一个项目可用于导入。 我能想到的是让项目成为一个“合法”的package,例如,在每个级别添加__init__.py ,更改导入包/函数的方式等。(实际上,我没有太多这样做的经验,而且我也不清楚如何做。)但是,我不认为这总是可行的,尤其是当该项目规模很大并且可能需要对项目结构的设计有公平的理解时。

总而言之,我的问题是,我应该怎么做才能在该项目之外导入第三方 python 项目而不将其添加到sys.path ,即使该项目可能设计为仅在其顶级目录级别运行?


编辑 #1 (20220819)

在@Lenntror 的评论之后,我在这里添加了一个最小的示例。 目标是从ProjectA ProjectA.lib.functions.xxxProjectA添加到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.pyProjectAProjectB位于同一目录中。

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM