如何从父目录进行相对导入?

时间:2017-11-17 01:35:07

标签: python relative-import

我搜索了这个并找到了很多答案,所有答案都告诉我要完成我正在做的事情,这是我的目录结构:

app/
+-- __init__.py
+-- app_manager.py
+-- app_gui/
|   +-- __init__.py
|   +-- app_gui.py
app_gui.py中的

我有:

import tkinter as tk
from tkinter import ttk
from app_manager import AppManager

在app manager中:

class AppManager():
    def __init__(self):
    """ default constructor for app manager """

在Visual Code中,它实际上将其解析为自动完成,这告诉我至少Visual Code将其视为正确完成。但是,如果我运行它,我会收到以下错误:

ModuleNotFoundError: No Module named "app_manager"

修改

更改为from app.app_manager import AppManager时的完整堆栈跟踪:

Traceback (most recent call last):
   File ".\app_gui\app_gui.py", line 4, in <module>
     from app_manager import AppManager
ModuleNotFoundError: No module named 'app_manager' 

2 个答案:

答案 0 :(得分:2)

由于app_manager.pyapp_gui.py上方的目录,我相信您的导入(如果您希望使用相对导入)应为

from ..app_manager import AppManager

编辑以解决评论中的错误:如果您尝试直接运行此文件,您将在评论中获得ValueError。相对导入在包内的模块之间工作。让我们假设您使用我上面写的导入,然后您在app名为stuff.py的{​​{1}}目录下面有一个文件,其中包含以下内容:

import app.app_gui.app_gui
print('hello')

运行stuff.py看起来像:

$ python stuff.py 
hello

换句话说,使用python解释器直接执行具有相对导入的文件将导致错误,因为它不打算以这种方式使用。相反,您的模型应该由模块本身之外的东西导入和执行。

如果__main__目录中的app文件具有完全相同的代码,您也可以直接执行该模块。

$ cat app/__main__.py 
import app.app_gui.app_gui
print('hello')

$ python -m app
hello

答案 1 :(得分:0)

运行这样的python代码充其量只是hacky。

使用setup.py
这将需要一些小的改变,但会立即支付利益 然后,您就可以像使用任何其他已安装的软件包一样使用app软件包。

新目录结构

.
├── app
│   ├── app_gui
│   │   ├── app_gui.py
│   │   └── __init__.py
│   ├── app_manager.py
│   └── __init__.py
└── setup.py

setup.py

from setuptools import find_packages, setup

setup(name='app',
      version='0.0.1-dev',
      description='My app package',
      install_requires=['tkinter'],
      packages=find_packages(),
      zip_safe=False)

app_gui.py

from app.app_manager import AppManager

manager = AppManager()

全部放在一起

setup.py运行相同的目录:
  $> python setup.py develop

这会将软件包符号链接到您的site-pacakges文件夹中,您可以将其视为任何其他软件包。即使用位于系统任何位置的脚本中的import app导入它。