Handling complicated directory structure with python imports
python
Solution
It really helps if, instead of thinking in terms of "file structure" first and then trying to figure out the packages, you design things in terms of packages, and then lay out your file structure to implement those packages.
But if you want to know how to hack up what you already have: If you put this at the top level (that is, in one of the paths on your `sys.path`), and create files names `ui/__init__.py` and `web/__init__.py`, then:
- `app.py` can be run as a script.
- `app.py` can be run with `-m app`.
- `app.py` can be imported with `import app`.
- `window.py` cannot be run directly.
- `window.py` can be run with `-m ui.window`.
- `window.py` can be imported with `import ui.window`.
- `connection.py` cannot be run directly.
- `connection.py` can be run with `-m web.connection`.
- `connection.py` can be imported with `import web.connection`.
No wacky path magic is needed; you just need the top level (with `app.py`, `constants.py`, `ui`, and `web`) to be on your `sys.path`—which it automatically is when you run with that directory as your working directory, or install everything directly into `site-packages`, or install it as an egg, etc.
That's as close as you're going to get to what you want. You do ever want to run code with a package directory as your current working directory or otherwise on `sys.path`, so don't even try. If you think you need that, what you probably want is to separate the runnable code out into a script that you can put at the top level, or somewhere entirely separate. (For example, look at `pip` or `ipython`, which installs scripts into somewhere on your system `$PATH` that do nothing but import some module and run a function.)
The only other thing you might want to consider is putting all of this into a package, say, `myapp`. You do that by adding a top-level `__init__.py`, and then running from the parent directory, and adding `myapp.` to the start of all your `import`and `-m` statements. That means you can no longer run `app.py` as a script either, so again you will need to split the script code out into a separate file from the module that does all the work.
Problem
I've worked on several medium-sized python applications to date, and every time it seems like I cobble together a terrible system of imports from tangential Stack Overflow answers and half-understood blog posts. It's ugly and hard to maintain and ultimately very unsatisfying. With this question I attempt to put all that behind me. Say I have a python application split into the following files: ``` app.py constants.py ui/window.py web/connection.py ``` With the following include requirements: - `app.py` needs to include `window.py` and `connection.py` - `window.py` needs to include `constants.py` and `connection.py` - `connection.py` needs to include `constants.py` `app.py` is the starting point for the application, but `window.py` and `connection.py` are also invokable from the command line to test basic functionality (ideally from within their respective folders). What combination of `__init__.py` files, carefully crafted import statements and wacky python path magic will allow me to achieve this structure? Thanks very much, --Dan