如何从父目录进行相对导入?
How to do a relative import from the parent directory?
我搜索了这个并找到了很多答案,所有答案都告诉我做我正在做的事情,这是我的目录结构:
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
在应用程序管理器中:
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'
由于 app_manager.py
是 app_gui.py
之上的目录,我相信您的导入(如果您希望使用相对导入)应该是
from ..app_manager import AppManager
编辑以解决评论中的错误:如果您尝试直接 运行 此文件,您将在评论中得到一个 ValueError
。相对导入在包内的模块之间工作。假设您使用我上面写的导入,然后您有一个名为 app
目录的上一级文件 stuff.py
,其内容如下:
import app.app_gui.app_gui
print('hello')
运行 stuff.py
看起来像:
$ python stuff.py
hello
换句话说,直接使用 python 解释器执行具有相对导入的文件将导致错误,因为它不打算以这种方式使用。相反,您的模型应该由模块本身之外的东西导入和执行。
如果您的 app
目录中有一个具有完全相同代码的 __main__
文件,您也可以直接执行该模块。
$ cat app/__main__.py
import app.app_gui.app_gui
print('hello')
$ python -m app
hello
运行 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
从位于系统任何位置的脚本导入它。
我搜索了这个并找到了很多答案,所有答案都告诉我做我正在做的事情,这是我的目录结构:
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
在应用程序管理器中:
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'
由于 app_manager.py
是 app_gui.py
之上的目录,我相信您的导入(如果您希望使用相对导入)应该是
from ..app_manager import AppManager
编辑以解决评论中的错误:如果您尝试直接 运行 此文件,您将在评论中得到一个 ValueError
。相对导入在包内的模块之间工作。假设您使用我上面写的导入,然后您有一个名为 app
目录的上一级文件 stuff.py
,其内容如下:
import app.app_gui.app_gui
print('hello')
运行 stuff.py
看起来像:
$ python stuff.py
hello
换句话说,直接使用 python 解释器执行具有相对导入的文件将导致错误,因为它不打算以这种方式使用。相反,您的模型应该由模块本身之外的东西导入和执行。
如果您的 app
目录中有一个具有完全相同代码的 __main__
文件,您也可以直接执行该模块。
$ cat app/__main__.py
import app.app_gui.app_gui
print('hello')
$ python -m app
hello
运行 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
从位于系统任何位置的脚本导入它。