pythonpython-3.xpython-importpython-packaging

Why is python thinking my folder is a module?


I have a project structured like this:

project+
       |-folder1+
       |        |-__init__.py
       |        |-script
       |
       |-folder2+
       |        |-__init__.py
       |        |-folder_3
       |        |-some_file.py
       |
       |-__init__.py

I tried to import file into script (which is the file being run) like this:

from project.folder2 import some_file as file

but it failed as:

ModuleNotFoundError: No module named 'project'

This doesn't even make sense, because 'project' should be a package, not a module. How would I do this? Would I need a different approach than that if I wanted to import something from folder_3?

Update: When I made the code I was running into a function, imported script to a file outside of project, and called the function, it worked. However, I do still want to know if there is a way to get it to work with the main file being script, not some file outside of project.


Solution

  • As a matter of terminology, the import messages refer to "modules" even when the import is logically importing a package. Even for a case like from x.y import z it doesn't know x, let alone y, is or is not a package (x could be a module importing a separate module it calls y, as with os.path where os is a module, importing posixpath under the alias path). When it doesn't find it, it can't even know if x was supposed to be a module or package, because it wasn't found.

    Think of "module" as meaning "module or package" in most messages, don't get hung up on minor terminology differences, it's an error message, not a language spec.

    As for why it's not found:

    1. Clearly the parent of project is not in sys.path
    2. Even if it was, from project.script import ANYTHING is clearly wrong, since you're omitting folder1 from the name, the folder structure means the module is project.folder1.script. Note, if script is a file (true module), not a directory, you named it wrong; it must have a .py extension to be imported (barring hacking around in the import mechanism to change this default)

    Odds are, you want to make a real package and install it (in a virtualenv, with --user for personal use, whatever) and after installation, it's automatically placed in a site-packages directory that sys.path will look in (barring the unusual case when the site module is not imported).