0

This is roughly my relevant folder structure:

 renny
|
|____ app
     |____ __init__.py
     |____ chatbox.py
|
|____ utils
     |____ __init__.py
     |____ wids.py
|
|____ main.py

The main.py imports the chatbox.py script, and the chatbox.py script imports the wids.py script.

When I run the main.py I get no issues, but I can't run the chatbox.py script directly, I get ModuleNotFoundError: No module named 'utils'

I assume it's because it is in a folder up, but it shouldn't be a problem since all folders have the __init__.py file.

Furthermore, I tried moving the utils folder to the app folder, but now I get the same problem when I run the main.py file. It makes sense since it's not in the same folder anymore, but it shouldn't do that.

I tried reopening VSCode, I tried from another computer, I tried with or without virtual enviroment, I tried restructuring the entire folder.

I think it should work right away, but I read somewhere that I should create a setup.py, which I'm not very familiar with, or that I should install the dependencies as a separate package, or that I should add the utils folder to the path. I understand I should learn how to do the setup.py thingy, but it's a really small project and I don't think I should create an installable python package just for a little function. It is really my first project and I want to understand why it doesn't work as it should.

Also, I verified "sys.path" and it only includes these:

['c:\\Benaj\\Desktop\\renny\\app',
'C:\\Users\\Benaj\\AppData\\Local\\Programs\\Python\\Python310\\python310.zip',
'C:\\Users\\Benaj\\AppData\\Local\\Programs\\Python\\Python310\\DLLs',
'C:\\Users\\Benaj\\AppData\\Local\\Programs\\Python\\Python310\\lib',
'C:\\Users\\Benaj\\AppData\\Local\\Programs\\Python\\Python310',
'c:\\Benaj\\Desktop\\renny\\env',
'c:\\Benaj\\Desktop\\renny\\env\\lib\\site-packages']

Should it include the utils folder?

mkrieger1
  • 19,194
  • 5
  • 54
  • 65
  • 2
    Related: [Relative imports for the billionth time](https://stackoverflow.com/q/14132789/11082165). The answers there dive into some common confusions about packages vs directories and scripts vs modules. – Brian61354270 Aug 09 '23 at 13:21
  • Do you intend for `renny` to be the top-level package, or for `app` and `utils` to be two different top-level packages? – Brian61354270 Aug 09 '23 at 13:22
  • 1
    Also, re _"I read somewhere that I should create a setup.py"_, `setup.py` is outdated. These days there are much more modern build systems that are _way_ simpler to use that use `pyproject.toml` files. You may want to look into [poetry](https://python-poetry.org/), [hatch](https://hatch.pypa.io/latest/), [flit](https://flit.pypa.io/en/stable/), etc. – Brian61354270 Aug 09 '23 at 13:23
  • 1
    As a personal aside re _"it's a really small project and I don't think I should create an installable python package just for a little function"_, some anecdotal notes: 1) creating installable packages is super simple these days (often little to _zero_ config required), and 2) installing your project saves your from re-inventing the wheel when you need to organize code between multiple files, and 3) it makes your development environment _so much_ nicer and consistent (stable Python path, imports aren't sensitive to the CWD, static analysis works better, you can use build system entrypoints...) – Brian61354270 Aug 09 '23 at 13:39
  • @Brian61354270 Thanks a lot, this very very useful! However, this part says "For either of these solutions, the package directory must be accessible from the Python module search path (sys.path). If it is not, you will not be able to use anything in the package reliably at all." I can't find it there. Why is that? I'll take a look into installable packages :) – Benjamin Bustelo Aug 09 '23 at 14:59
  • I'm not entirely sure what you mean by I can't find it there. But what passage is saying is that in order for `import X` to find `X`, `X` needs to be in a directory that's on the Python path. In practice, that either means copying `X` into a directory that's already on the Python path (which what happens by default when you install a package - it gets copied into your interpreter's `site-packages`) or adding the directory that `X` is in to your Python path (which is what happens with "editable" installs with `pip install -e`, or when you rely on Python prepending the CWD to the Python path) – Brian61354270 Aug 09 '23 at 15:06

1 Answers1

2

You have two top level packages in the same folder. You could add __init__.py to your renny directory to make it the top level package.

In chatbox.py import from your top level package from renny.utils import wids

In main.py import from your top level package from renny.app import chatbox

 Renny
|
|___ renny
    |
    |___ app
        |___ __init__.py
        |___ chatbox.py
    |
    |___ utils
        |____ __init__.py
        |____ wids.py
    |
    |___ __init__.py
|
|___ main.py
stan61285
  • 168
  • 7
  • 2
    A particular point to note is the separation of library and script code here. Keeping `main.py` outside of the `renny` package is essential - mixing scripts and modules only ends in tears. Also FWIW, adding `__init__.py` isn't strictly necessary since `renny` will still be an [implicit namespace package](https://peps.python.org/pep-0420/) without it – Brian61354270 Aug 09 '23 at 14:31
  • thank you! I clearly don't understand packages. Then, as I proposed it "renny" works as a package? Why shouldn't the `main.py` be inside that second `renny` folder? Im a little lost – Benjamin Bustelo Aug 10 '23 at 03:33
  • If it is a script, leave it out and if it is a library you don't need it. If you are wanting to run it from console like `py -m renny` then use `__main__.py` in `renny` instead. – stan61285 Aug 10 '23 at 17:52