从当前工作目录上方的目录导入模块

Importing module from a directory above current working directory

首先,Whosebug 上有很多关于此的解决方案,但我尝试过的解决方案 none 是有效的。我正在远程机器上工作 (linux)。我正在使用 ipython 解释器在 dir-2/module_2.py 文件中制作原型。此外,我试图避免使用绝对路径,因为这台远程机器中的绝对路径又长又丑,我希望我的代码在下载后在其他机器上 运行。

我的目录结构如下:

/project-dir/
            -/dir-1/
                  -/__ init__.py
                  -/module_1.py
            -/dir-2/
                  -/__ init__.py
                  -/module_2.py
                  -/module_3.py

现在我想从 module_2 导入 module_1。然而这个Whosebug post中提到的解决方案: of using

sys.path.append('../..')
import module_2

无效。我收到错误:ModuleNotFoundError: No module named 'module_1'

此外,在 ipython 解释器中 module_2 中的 import .module_3 会抛出错误:

import .module_3
       ^ SyntaxError: invalid syntax

点运算符不应该在同一目录中工作吗?总的来说,我对导入机制感到很困惑。非常感谢对最初问题的任何帮助!非常感谢!

为什么它不起作用?

如果你 运行 module1.py 文件并且你想导入 module2 那么你需要像

sys.path.append("../dir-2")

如果你在其中使用 sys.path.append("../..") then the folder you added to the path is the folder containing project-dirand there is notmodule2.py` 文件。


语法import .module_3 用于相对导入。如果您尝试执行 module2.py 并且它包含 import .module_3 它不起作用,因为您正在使用 module2.py 作为脚本。要使用相对导入,您需要将 module2.pymodule_3.py 都视为模块。也就是说,一些其他文件导入 module2 和 module2 使用此语法从 module3 导入某些内容。

关于如何继续的建议

解决这两个问题的一个可能解决方案是 属性 组织项目和(可选,这是一个好主意)打包您的库(即,使您的代码“可安装”)。然后,一旦你的库安装好了(在你工作的虚拟环境中),你就不需要 hacky sys.path solutions。您将能够从任何文件夹导入您的库。

此外,不要将您的模块视为脚本(不要 运行 您的模块)。使用单独的 python 文件作为您的“可执行文件”(或入口点)并从那里导入您需要的所有内容。这样,您的 module*.py 文件中的相对导入将正常工作,您不会感到困惑。

一个可能的目录结构可能是

/project-dir/
            - apps/
                  - main.py
            - yourlib/
                  -/__ init__.py
                  -/dir-1/
                        -/__ init__.py
                        -/module_1.py
                  -/dir-2/
                        -/__ init__.py
                        -/module_2.py
                        -/module_3.py

请注意 yourlib 文件夹及其子文件夹包含一个 __init__.py 文件。使用此结构,您只需 运行 main.py(名称不需要 main.py)。

情况 1:您不想打包您的库

如果您不想打包您的库,那么您可以在 main.py 中添加 sys.path.append("../") 以将“project-dir/ 文件夹添加到路径中。这样您的 yourlib 库将在 main.py 中“导入”。您可以执行类似 from yourlib import module_2 的操作,它会正常工作(并且 module_2 可以使用相对导入)。或者,您也可以直接将 main.py 放入 project-dir/ 文件夹中,您根本不需要更改 sys.path,因为在这种情况下 project-dir/ 将成为“工作目录”。

请注意,您还可以在 project-dir 中有一个 tests 文件夹,并且 运行 一个测试文件,您可以像 运行 main.py.

情况 2:您想打包您的图书馆

之前的解决方案已经解决了您的问题,但更进一步会带来一些好处,例如依赖管理,并且无论您身在何处都无需更改 sys.path。有几个选项可以打包你的库,我将使用 poetry 显示一个选项,因为它很简单。

安装poetry后,可以运行在终端中输入下面的命令新建一个项目

poetry new mylib

这将创建以下文件夹结构

mylib/
     - README.rst
     - mylib/
            - __init__.py
     - pyproject.toml
     - tests

然后您可以根据需要添加 apps 文件夹,以及 mylib/ 中的子文件夹(每个子文件夹都有一个 __init__.py 文件)。

pyproject.toml 文件指定依赖项和项目元数据。可以手动编辑and/or使用诗歌添加新的依赖,比如

poetry add pandas
poetry add --dev mypy
例如,

添加 pandas 作为依赖项和 mypy 作为开发依赖项。之后,您可以运行

poetry build

创建虚拟环境并在其中安装您的库。您可以使用 poetry shell 激活虚拟环境,您将能够从任何地方导入您的库。请注意,您可以更改库文件而无需再次 运行 poetry build

最后,如果你想在 PyPi 中发布你的库供大家查看,你可以使用

poetry publish --username your_pypi_username --password _passowrd_

TL;博士

使用有条理的项目结构,并为您执行的脚本提供清晰的位置。特别是,如果您执行的脚本位于包含您的模块的文件夹之外会更好。另外,不要 运行 将模块作为脚本(否则你不能使用相对导入)。