简体   繁体   中英

Referencing a custom module in a parent or grandparent folder results in 'ModuleNotFoundError: No module named' in Python

Explanation

Use Case : Reference a top-level <module_name>.py module from a low-level (subfolder) <script_name>.py

I was under the impression one could import python scripts and their respective variables into other scripts within a project directory as long as they all had a main directory in common.

.
└── spam/                    Main directory (git repo)
    ├── spam/                Main project directory
    │   ├── __init__.py
    │   ├── ham/             Directory within main project spam/
    │   │   ├── __init__.py
    │   │   └── eggs.py      Script within sub directory ham/
    │   └── config.py        Config with contents eggs.py needs
    └── README.md

(Note: Yes, the main directory and the main project directory have the same name.)

For example, I thought the above structure would allow this behavior: use contents from config with eggs.py

#! /spam/spam/ham/eggs.py

from spam import config

Well, not quite...

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ModuleNotFoundError: No module named 'spam'

So I took one step back.

#! /spam/spam/ham/eggs.py

import spam
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ModuleNotFoundError: No module named 'spam'

I was wrong.

I am not so much looking for a solution at this point (since I found a few different ones including here and here (though the explanations did not really get through my thick skull). Would anyone like to explain it to me like I'm a 5th grader?

I will continue to collect what I consider to be valuable resources for finding the answers to my question. I appreciate all contributions that help clear up this picture.

Ongoing Discoveries

Exploratory Testing

../垃圾邮件

Imports work for the above image.

# ../spam
# Direct import statements.
import spam
import config

# Indirect to get ham.
import spam.ham
from spam import ham

# Indirect to get eggs.
import spam.ham.eggs
from spam.ham import eggs

../垃圾邮件/垃圾邮件

Imports work for the above image.

# ../spam/spam
# Direct import statements.
import ham

# Indirect to get eggs.
import ham.eggs
from ham import eggs

../垃圾邮件/垃圾邮件/火腿

Imports work for the above image.

# ../spam/spam/ham
# Direct import statements.
import eggs

Observations

  • when doing import <module_name> , the current directory is checked but "backwards blind"
  • namespaces play a key role here
  • relative imports are only for use within module files (ie, not within interactive interpreters)

Resources for Better Understanding

*Solutions I test and find acceptable.


Tools and Versions

Python 3.8.6

A python module is not a folder, it's a python file (eg iamapythonfile.py)

Then your "spam" folder could not be resolved as a python module

you may use

 import modulename.py

#or

from modulename.py import yourfunction

Then you should care about the path (absolute or relative )

More informations at: https://www.learnpython.org/en/Modules_and_Packages#:~:text=Modules%20in%20Python%20are%20simply,or%20variables%20defined%20and%20implemented .

EDIT : i've just found this https://realpython.com/absolute-vs-relative-python-imports/#:~:text=You%20need%20to%20have%20a,init__.py%20file ). , it's well explained and clear. Enjoy.

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