1

I have a question. I have a directory setup like this:

folder/
       main.py
       /stuff/
             __init__.py
             function.py
       /items/
             __init__.py
             class.py

My question is how would I import the class.py into the function.py? This setup is very specific and is unable to be changed. What would I need to put in order for this to work?

Punisher
  • 23
  • 1
  • 4
  • Add the parent folder to you PYTHONPATH (`sys.path.append(...)`) and then you simply do `from stuff init function` in `class.py`. That's one solution… – tamasgal Dec 07 '14 at 16:13
  • Possible duplicate of http://stackoverflow.com/questions/72852/how-to-do-relative-imports-in-python – kdopen Dec 07 '14 at 16:20
  • Definite duplicate of http://stackoverflow.com/questions/27215912/import-neighboring-module-in-python/27216343#27216343 – kdopen Dec 07 '14 at 16:21
  • 1
    The answer is `from .. import items` or `from ..items import class` – kdopen Dec 07 '14 at 16:22
  • I tried the from .. import items but I kept getting this error: ValueError: Attempted relative import beyond toplevel package – Punisher Dec 08 '14 at 14:08

1 Answers1

4

Your current directory structure seems ideal, so long as the application is started via main.py.

Python will always automatically add the parent directory of the main script to the start of sys.path (i.e. folder in your example). This means that the import machinery will give that directory priority when searching for modules and packages that are not part of the standard libarary.

Given this, you can import the classes.py module into function.py, like so:

from items import classes

(Note that I have renamed the module, because class is a python keyword).

If you later added another module to stuff, and wanted to import it into functions.py, you would do:

from stuff import another

and if a sub-package was added to items, and you wanted to import a module from that, you would do:

from items.subpackage import module

Imports specified in this top-down way can be used from any module within the application, because they are always relative to the parent directory of the main script, which has priority.

ekhumoro
  • 115,249
  • 20
  • 229
  • 336
  • Does not work for me. Could you please explain how this works because I have the same architecture with `__init__.py` file in each folder but when I try to import it does not work. – Yohan Obadia Aug 02 '17 at 07:55
  • @YohanObadia. There's not much I can add to my answer, which explains it pretty well. You **must** start the application using a *main.py* script which is in the directory containing the packages. The container directory is not itself a package. The question shows the correct directory structure very clearly. – ekhumoro Aug 02 '17 at 11:02
  • This is what I mean by more details. Do you need a `main.py`? If yes why and can it be empty like an `__init__.py` file. I think it would had some clarity to your answer. – Yohan Obadia Aug 02 '17 at 11:12
  • @YohanObadia. I think it's self-evident that you need to run a script to start an application. The conventional name for such a script is *main.py*, but you can call it what you like. Honestly, you are making this *much, much* more complicated than it really is :-). All you need to do is put your start-up script in the directory containing the packages. That is literally all there is to it. If you can't get that to work for some reason, you will need to give full details of your particular directory structure and any error messages you receive. – ekhumoro Aug 02 '17 at 11:32
  • In my particular case, I am creating 4 folders in which different processes are running. I actually do not need a main script. And using your method I could not get my 4 folders to communicate. I had to use `sys.path.insert(0, '../')` to be able to do the import needed. Basically I have one folder with a web-app running with flask, one folder that keep all the database scripts, one to run a daily script that update the database that the website needs and a 4th one that is used by the web-app and the daily script. – Yohan Obadia Aug 02 '17 at 11:48
  • 2
    @YohanObadia. Your application has scripts which start various processes. If you want all the imports to work without ugly `sys.path` hacks, these start-up scripts **must** be in the top-level container directory, rather than sub-directories. That is how Python is designed to work, and so that is what my answer is based on. – ekhumoro Aug 02 '17 at 12:15