从当前工作目录上方的目录导入模块 [英] Importing module from a directory above current working directory

查看:39
本文介绍了从当前工作目录上方的目录导入模块的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

首先,有很多关于stackoverflow的解决方案,但是从我尝试过的解决方案中,没有一个起作用.我正在远程计算机(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 .但是此stackoverflow帖子中提到的解决方案:链接使用

  sys.path.append('../..')导入模块_2 

不起作用.我收到错误消息: ModuleNotFoundError:没有名为"module_1"的模块

此外,在ipython解释器中,诸如 module_2 中的 import .module_3 之类的错误引发:

  import .module_3^ SyntaxError:语法无效 

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

解决方案

为什么不起作用?

如果运行 module1.py 文件,并且要导入 module2 ,则需要类似

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

如果使用 sys.path.append("../.."),则添加到路径的文件夹是包含 project-dir 的文件夹不是 module2.py`文件.


import .module_3 语法用于相对导入.如果您尝试执行 module2.py 并且其中包含 import .module_3 ,则该代码将不起作用,因为您将 module2.py 用作脚本.要使用相对导入,您需要将 module2.py module_3.py 都视为模块.也就是说,其他一些文件导入module2和module2使用此语法从module3导入一些东西.

关于如何进行的建议

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

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

可能是可能的目录结构

 /project-dir/- 应用/-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 中.您可以从liblib导入module_2 中执行之类的操作,它将正常工作(并且 module_2 可以使用相对导入).另外,您也可以直接将 main.py 放在 project-dir/文件夹中,而无需在以下位置更改 sys.path 因为 project-dir/将是工作目录",在这种情况下.

请注意,您还可以在 project-dir 中包含一个 tests 文件夹,并且要运行测试文件,您可以执行与运行 main相同的操作.py .

情况2:您想打包您的库

先前的解决方案已经解决了您的问题,但加倍努力会带来一些好处,例如依赖管理,并且无论您身在何处都无需更改 sys.path .打包您的库有几种选择,由于其简单性,我将使用诗歌显示一个选择.>

安装诗歌后,您可以在终端中运行以下命令来创建新项目

 诗歌新的mylib 

这将创建以下文件夹结构

  mylib/-README.rst-mylib/-__init__.py-pyproject.toml-测试 

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

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

 诗歌添加熊猫诗歌添加--dev mypy 

例如,

pandas 添加为依赖项,将 mypy 添加为开发依赖项.之后,您可以运行

 诗歌构建 

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

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

 <代码>诗歌发布--username your_pypi_username --password _passowrd_ 


TL;DR

对您执行的脚本使用有条理的项目结构,并留有清晰的位置.特别是,如果您执行的脚本位于模块所在文件夹的外部,则更好.另外,请勿将模块作为脚本运行(否则您不能使用相对导入).

First of all, there are a bunch of solutions on stackoverflow regarding this but from the ones I tried none of them is working. I am working on a remote machine (linux). I am prototyping within the dir-2/module_2.py file using an ipython interpreter. Also I am trying to avoid using absolute paths as the absolute path in this remote machine is long and ugly, and I want my code to run on other machines upon download.

My directory structure is as follows:

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

Now I want to import module_1 from module_2. However the solution mentioned in this stackoverflow post: link of using

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

Does not work. I get the error: ModuleNotFoundError: No module named 'module_1'

Moreover, within the ipython interpreter things like import .module_3 within module_2 throws error:

import .module_3
       ^ SyntaxError: invalid syntax

Isn't the dot operator supposed to work within the same directory as well. Overall I am quite confused by the importing mechanism. Any help with the initial problem is greatly appreciated! Thanks a lot!

解决方案

Why it didn't work?

If you run the module1.py file and you want to import module2 then you need something like

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

If you use sys.path.append("../..") then the folder you added to the path is the folder containing project-dirand there is notmodule2.py` file inside it.


The syntax import .module_3 is for relative imports. if you tried to execute module2.py and it contains import .module_3 it does not work because you are using module2.py as a script. To use relative imports you need to treat both module2.py and module_3.py as modules. That is, some other file imports module2 and module2 import something from module3 using this syntax.

Suggestion on how you can proceed

One possible solution that solves both problems is property organizing the project and (optionally, ut a good idea) packaging your library (that is, make your code "installable"). Then, once your library is installed (in the virtual environment you are working) you don't need hacky sys.path solutions. You will be able to import your library from any folder.

Furthermore, don't treat your modules as scripts (don't run your modules). Use a separate python file as your "executable" (or entry point) and import everything you need from there. With this, relative imports in your module*.py files will work correctly and you don't get confused.

A possible directory structure could be

/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

Notice that the the yourlib folder as well as subfolders contain an __init__.py file. With this structure, you only run main.py (the name does not need to be main.py).

Case 1: You don't want to package your library

If you don't want to package your library, then you can add sys.path.append("../") in main.py to add "the project-dir/ folder to the path. With that your yourlib library will be "importable" in main.py. You can do something like from yourlib import module_2 and it will work correctly (and module_2 can use relative imports). Alternatively, you can also directly put main.py in the project-dir/ folder and you don't need to change sys.path at all, since project-dir/ will be the "working directory" in that case.

Note that you can also have a tests folder inside project-dir and to run a test file you can do the same as you did to run main.py.

Case 2: You want to package your library

The previous solution already solves your problems, but going the extra mile adds some benefits, such as dependency management and no need to change sys.path no matter where you are. There are several options to package your library and I will show one option using poetry due to its simplicity.

After installing poetry, you can run the command below in a terminal to create a new project

poetry new mylib

This creates the following folder structure

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

You can then add the apps folder if you want, as well as subfolders inside mylib/ (each with a __init__.py file).

The pyproject.toml file specifies the dependencies and project metadata. You can edit it by hand and/or use poetry to add new dependencies, such as

poetry add pandas
poetry add --dev mypy

to add pandas as a dependency and mypy as a development dependency, for instance. After that, you can run

poetry build

to create a virtual environment and install your library in it. You can activate the virtual environment with poetry shell and you will be able to import your library from anywhere. Note that you can change your library files without the need to run poetry build again.

At last, if you want to publish your library in PyPi for everyone to see you can use

poetry publish --username your_pypi_username --password _passowrd_


TL; DR

Use an organized project structure with a clear place for the scripts you execute. Particularly, it is better if the script you execute is outside the folder with your modules. Also, don't run a module as a script (otherwise you can't use relative imports).

这篇关于从当前工作目录上方的目录导入模块的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆