python - 从当前工作目录上方的目录导入模块
问题描述
首先,stackoverflow 上有很多关于此的解决方案,但从我尝试过的解决方案中,它们都不起作用。我正在使用远程机器(linux)。我正在dir-2/module_2.py
使用 ipython 解释器在文件中进行原型设计。此外,我试图避免使用绝对路径,因为这台远程机器中的绝对路径又长又丑,我希望我的代码在下载后能在其他机器上运行。
我的目录结构如下:
/project-dir/
-/dir-1/
-/__ init__.py
-/module_1.py
-/dir-2/
-/__ init__.py
-/module_2.py
-/module_3.py
现在我想module_1
从module_2
. 但是这个stackoverflow帖子中提到的解决方案:使用链接
sys.path.append('../..')
import module_2
不工作。我得到错误:ModuleNotFoundError: No module named 'module_1'
此外,在 ipython 解释器中,诸如 inside 之类的东西import .module_3
会module_2
抛出错误:
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-dir and there is not
module2.py` 文件。
该语法import .module_3
用于相对导入。如果您尝试执行module2.py
并且它包含import .module_3
它不起作用,因为您将module2.py
其用作脚本。要使用相对导入,您需要同时将module2.py
和module_3.py
视为模块。也就是说,其他一些文件导入 module2 和 module2 使用此语法从 module3 导入某些内容。
关于如何进行的建议
解决这两个问题的一种可能的解决方案是组织项目的属性和(可选地,一个好主意)打包您的库(即,使您的代码“可安装”)。然后,一旦安装了您的库(在您正在工作的虚拟环境中),您就不需要hackysys.path
解决方案。您将能够从任何文件夹导入您的库。
此外,不要将您的模块视为脚本(不要运行您的模块)。使用单独的 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:你不想打包你的库
如果您不想打包您的库,那么您可以添加sys.path.append("../")
以main.py
将“project-dir/
文件夹添加到路径中。这样您的yourlib
库将是“可导入”的main.py
。您可以执行类似的操作from yourlib import module_2
,它会正常工作(并且module_2
可以使用相对导入)。或者,您也可以直接放入main.py
文件project-dir/
夹,根本不需要更改sys.path
,因为project-dir/
在这种情况下将是“工作目录”。
请注意,您还可以在其中有一个tests
文件夹project-dir
并运行测试文件,您可以像运行main.py
.
案例 2:你想打包你的库
之前的解决方案已经解决了您的问题,但加倍努力会增加一些好处,例如依赖关系管理,并且sys.path
无论您身在何处都无需更改。打包你的图书馆有几个选项,由于它的简单性,我将使用诗歌来展示一个选项。
安装诗歌后,您可以在终端中运行以下命令来创建一个新项目
poetry new mylib
这将创建以下文件夹结构
mylib/
- README.rst
- mylib/
- __init__.py
- pyproject.toml
- tests
然后,您可以根据需要添加apps
文件夹以及其中的子文件夹mylib/
(每个都有一个__init__.py
文件)。
该pyproject.toml
文件指定依赖项和项目元数据。您可以手动编辑它和/或使用诗歌添加新的依赖项,例如
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; 博士
使用有组织的项目结构,为您执行的脚本提供清晰的位置。特别是,如果您执行的脚本位于您的模块所在的文件夹之外,则效果会更好。另外,不要将模块作为脚本运行(否则您不能使用相对导入)。
推荐阅读
- c - 我的指针没有返回 NULL,但它正在痛苦的文件不存在
- applescript - 从applescript更改屏幕截图的目录
- javascript - 在第三方服务器上使用 JSON
- c# - 在无状态环境中跨多个请求保持对文件的锁定(Asp.Net Core)
- python - PySpark 2.2 爆炸删除空行(如何实现explode_outer)?
- azure - 如何在 Visual Studio 2015 或 2017 中为 ssis 中的 sql server 2016 启用 azure blob 枚举器
- javascript - 同一页面中的多个日期选择器
- stripe-payments - 将付款拆分给多个商家
- java - 数组初始化作为Java中的实例变量的问题
- r - 获取矩阵行中出现次数最多的数字并连接结果