首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >从当前工作目录上的目录导入模块

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

Stack Overflow用户
提问于 2020-09-28 18:44:50
回答 1查看 1.7K关注 0票数 2

首先,关于这一点,有很多关于堆栈溢出的解决方案,但从我尝试过的那些解决方案来看,它们都不起作用。我正在开发一台远程计算机(linux)。我正在使用ipython解释器在dir-2/module_2.py文件中进行原型设计。此外,我还试图避免使用绝对路径,因为这台远程机器中的绝对路径又长又丑,我希望我的代码在下载时在其他机器上运行。

我的目录结构如下:

代码语言:javascript
复制
/project-dir/
            -/dir-1/
                  -/__ init__.py
                  -/module_1.py
            -/dir-2/
                  -/__ init__.py
                  -/module_2.py
                  -/module_3.py

现在,我想从module_1中导入module_2。但是,在这个堆栈溢出帖子中提到的解决方案:使用链接

代码语言:javascript
复制
sys.path.append('../..')
import module_2

不管用。我得到了错误:ModuleNotFoundError: No module named 'module_1'

此外,在ipython解释器中,如import .module_3module_2中抛出错误:

导入.module_3 ^ SyntaxError:无效语法

点操作符不也应该在同一个目录下工作吗。总的来说,我对进口机制感到很困惑。任何对初始问题的帮助都是非常感谢的!非常感谢!

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-09-28 22:24:41

为什么不起作用?

如果您运行module1.py文件,并且希望导入module2,那么您需要如下所示

代码语言:javascript
复制
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导入一些东西。

关于如何进行的建议

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

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

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

代码语言:javascript
复制
/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。有几个选项可以打包您的库,由于它的简单性,我将展示一个使用诗歌的选项。

安装完诗歌之后,可以在终端中运行下面的命令来创建一个新项目。

代码语言:javascript
复制
poetry new mylib

这将创建以下文件夹结构

代码语言:javascript
复制
mylib/
     - README.rst
     - mylib/
            - __init__.py
     - pyproject.toml
     - tests

然后,如果需要,可以添加apps文件夹,也可以在mylib/中添加子文件夹(每个文件夹都有一个__init__.py文件)。

pyproject.toml文件指定依赖项和项目元数据。您可以手工编辑它和/或使用诗歌添加新的依赖项,例如

代码语言:javascript
复制
poetry add pandas
poetry add --dev mypy

例如,将pandas添加为依赖项,将mypy添加为开发依赖项。在那之后,你可以跑

代码语言:javascript
复制
poetry build

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

最后,如果您想在PyPi中发布您的库供每个人查看,您可以使用

代码语言:javascript
复制
poetry publish --username your_pypi_username --password _passowrd_

TL;DR

使用有组织的项目结构,为您执行的脚本提供一个清晰的位置。特别是,如果您执行的脚本与您的模块在文件夹之外,则更好。另外,不要将模块作为脚本运行(否则不能使用相对导入)。

票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/64107888

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档