1

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

../spam

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

../spam/spam

Imports work for the above image.

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

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

../spam/spam/ham

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 (i.e., not within interactive interpreters)

Resources for Better Understanding

*Solutions I test and find acceptable.


Tools and Versions

Python 3.8.6

Jesse H.
  • 465
  • 4
  • 12
  • question: did you first download spam package?? because of what I am seeing the package spam is not downloaded and spam is not a default package that comes with python. or am I not understanding your question?? – Shad0w Dec 03 '20 at 21:48
  • @Shad0w spam is one of a few metasyntactic variables in Python. I am using spam, ham, and eggs as placeholders like foo and bar. See this for more: https://en.wikipedia.org/wiki/Metasyntactic_variable – Jesse H. Dec 03 '20 at 22:00
  • Python searches for modules in the current directory and if it's not found, continues searching through each of the directories currently in the [`sys.path`](https://docs.python.org/3/library/sys.html#sys.path) list. There is not concept of "project" built into the language — although there is in many IDEs (and how to make them aware of where to search depends on which one you're using). – martineau Dec 03 '20 at 22:05
  • so spam is a function in a .py file and you are trying to import the function to another .py file? – Shad0w Dec 03 '20 at 22:10
  • @JesseH. if so its very straight foreword if the 2 different .py file in the the same folder you only need to first ```from .file_name import function_name``` and that tells python from this .py file that is in my folder give me the function which is```spam``` and if your function is for some reason to long you can use ````from file_name import function_name as fn``` . understand or should I explain it more? – Shad0w Dec 03 '20 at 22:14
  • @Shad0w that did not work. Also, not so much looking for a solution as an answer with the fundamentals of why. This is what occurred `ImportError: attempted relative import with no known parent package` – Jesse H. Dec 03 '20 at 22:24
  • @JesseH. what is your .py file name if its also spam python is getting confused between your .py file and a package called spam and this explain why you are getting your error for package is not installed just try changing the name of your .py file to something else and import the function from it like this ```from test import function_name``` (test is the name of the .py file) – Shad0w Dec 03 '20 at 22:28
  • @Shad0w thanks for the suggestions. I added a link why relative imports are not working. Also, I did a lot of testing on my end to gather some experience-based feedback. I will include those soon. – Jesse H. Dec 04 '20 at 19:03
  • @JesseH. very nice job on you're research. I have question have you ever considered reading books about programming? I would recommend reading books I really never understood somethings that I saw on YouTube tutorials and when I tried reading on my computer I always got distracted so I wanted to take a gamble and save some money to buy a book to get the basics down and for in my surprise books worked very good. (I never was so much interested in books before this, I am a beginner as well I started working on my programming skills in the last 2 months, and it really paid off) . – Shad0w Dec 04 '20 at 21:43
  • @Shad0w thanks for the recommendation. I find the combination of resources and practice has been working well for me. Best of luck to you! – Jesse H. Dec 04 '20 at 22:08

1 Answers1

0

A python module is not a folder, it's a python file (e.g. 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.

Adrien p
  • 66
  • 5
  • Thanks for responding. I've found realpython.com to be a great resource for most of my questions, but that article is also a bit verbose without tackling my specific use case: referencing a module object within a subdirectory of that module. In a sense, "reaching back." – Jesse H. Dec 04 '20 at 19:23