简体   繁体   中英

How to do a relative import from the parent directory?

I have searched this and found many answers, all of which tell me to do exactly what I am doing, here is my directory structure:

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

in app_gui.py I have:

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

in app manager:

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

In Visual Code, it actually resolves this to an auto completion, which tells me that at least Visual Code sees it as correctly done. However, if I run this I get the following error:

ModuleNotFoundError: No Module named "app_manager"

Edit

Full stack trace when changing to 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' 

Since app_manager.py is a directory above app_gui.py , I believe your import (if you wish to use a relative import) should be

from ..app_manager import AppManager

EDIT to address error in comments: If you try to run this file directly, you will get a ValueError like in the comments. Relative imports work between modules inside of packages. Let's say that you use the import I wrote above, and then you have a file ONE LEVEL ABOVE your app directory called stuff.py , with the following contents:

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

Running stuff.py would look like:

$ python stuff.py 
hello

In other words, executing a file with relative imports directly with the python interpreter will result in an error, as it was not intended to be used this way. Rather, your model should be imported and executed by something outside of the module itself.

If you have a __main__ file inside of your app directory with the exact same code, you can also execute the module directly.

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

$ python -m app
hello

Running python code like this is hacky at best.

Use a setup.py
This will require some small changes but will pay immediate benefits.
You will then be able to use your app package like any other installed package.

New Directory Structure

.
├── 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()

Putting it all together

From the same dir as setup.py run:
$> python setup.py develop

This will symlink the package into your site-pacakges folder where you can treat it like any other package. ie import it using import app from scripts located anywhere on your system.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM