1

I have a project organized as such:

proj
├── main.py
├── netbatch
│   ├── __pycache__
│   ├── monster.py
│   └── test_monster.py
└── workers
    ├── __pycache__
    ├── ldb
    │   ├── __pycache__
    │   └── handle.py
    └── strawberry.py

strawberry.py contains

import ldb.handle
...
if __name__ == '__main__':

and main.py contains

import workers.strawberry
import workers.ldb.handle

When I run strawberry.py the import works as expected, but when I run main.py, I see the error:

  File "/tmp/proj/workers/strawberry.py", line 3, in <module>
    import ldb.handle
ModuleNotFoundError: No module named 'ldb'

I'm using version 3.6.3

cMonster
  • 17
  • 1
  • 6
  • 1
    This has nothing to do with missing `__init__.py`. The issue is that running `python /tmp/proj/main.py` puts `/tmp/proj` on the path, but `strawberry.py` requires an import relative to its own directory which is not on the path (since it's located inside `/tmp/proj/workers`). – a_guest Jun 29 '20 at 19:26
  • @a_guest is there an elegant way to make both `main.py` and `strawberry.py` work as stand-alone scripts (without the `sys.path` hack?) – cMonster Jun 29 '20 at 20:19
  • 1
    You can make `proj` a package and install it, then you can use absolute imports like `import proj.workers.ldb.handle`. – a_guest Jun 29 '20 at 21:02
  • My suggestion: **1.** Fix your imports to make them all absolute, I will assume the top level packages are `workers` and `netbatch`, so something like that: `import workers.strawberry; import netbatch` or `from workers import strawberry`, etc. **2.** Add the package initializers (`__init__.py` files, maybe empty). **3.** Executable modules that are in packages have to be run like so: `python -m workers.strawberry`. On the other hand `main.py` doesn't seem to be part of a package and can be run like so: `python main.py`. **4.** **DO NOT** modify `sys.path` or `PYTHONPATH`. – sinoroc Jun 29 '20 at 22:03
  • @a_guest if I'm going to do that, shouldn't `ldb` be at the same level as `workers`? – cMonster Jun 29 '20 at 22:29
  • @sinoroc what if I want a symbolic link to `main` that a user can run without worrying about any of that? – cMonster Jun 29 '20 at 22:30
  • If you want to use a symbolic link (or something else to a similar effect), then I believe we'd have to rework a couple more things. Do it step by step. Have you tried my recommendations already, does it work as expected? – sinoroc Jun 30 '20 at 06:49
  • @cMonster It's not a problem, just install the whole `proj` as a package. Then you can run it from anywhere. By the way, symbolic links are resolved by your OS, so there's no difference from running `main.py` directly. – a_guest Jun 30 '20 at 07:24
  • @a_guest the issue with the _symlink_, or at least the underlining issue that I assumed from this symlink question is about the _current working directory_. If indeed the project is _installed_ (even better if in a virtual environment), then the current working directory doesn't matter much, we could even add some entry points for console scripts and use these from anywhere (absolute path to interpreter is in the shebang). No problem. **But** if it's not installed then the current working directory matters a lot. Anyway fixing the packaging and installing would be preferred, absolutely right. – sinoroc Jun 30 '20 at 10:40

0 Answers0