wsgi:error ModuleNotFoundError in my webapp model

Question:

Hello IT ladies and IT gentlemen.

Please, help me with non-recognized folder "devices".

I have a program for reading data from robot. And data are stored in "devices" folder.

My file structure:

  • GRP
    • devices
      • _ _ init _ _.py
      • dev1.py
      • dev2.py
      • dev3.py
      • webapp.py
    • tools
      • _ _ init _ _.py
      • tool1.py
      • tool2.py

Content of _ _ init _ _ .py in devices folder:

__all__ = ["dev1", "dev2", "dev3"]
from dev1 import Dev1Cls
from dev2 import Dev2Cls
from dev3 import Dev3Cls

Problematic part of code in webapp.py:

from devices import Dev1Cls

And… Dev1Cls is class in dev1.py

I have flask Webapp (blabla/grp_exp_structure/devices/webapp.py) whose task is to read data and display them. Webapp reads data from dev1, dev2 and dev3 and that webapp is launched from Apache server via mod_wsgi.

If I run app via built-in Werkzeug server, no problem.
But if I run app by start Apache, I get exception ModuleNotFoundError in errorlog:
ModuleNotFoundError: No module named ‘devices’

Code of app.wsgi:

#! C:/Users/pvachal/AppData/Local/Programs/Python/Python310/python.exe

import sys

sys.path.insert(0, "c:/users/pvachal/documents/projekty/grp_exp_structure/devices")

activate_this = "c:/users/pvachal/documents/projekty/grp_exp_structure/venv/scripts/activate_this.py"
with open(activate_this) as file_:
    exec(file_.read(), dict(__file__=activate_this))

from webapp import Webapp
application = Webapp().app

Code of dev1.py (dev2 and dev3 are similar)

class Dev1Cls:
    def __init__(self):
        self.value = "dev_number_one"

What do I have to do to make it work? I want to leave same file system what I have. Yes, I can change the structure of my files but I’m wondering how to solve this problem without changing the structure.

I think that problem is with non-reading of _ _ init _ _ file. When I run webapp.py directly, everything is alright because _ _ init _ _ file will launch. What I need to do to make it run without problems via wsgi? Is it possible to make _ _ init _ _ run via wsgi too?

Asked By: Petr

||

Answers:

Messing with sys.path is a terrible, terrible idea – with what you’ve done, you probably have two ways of importing dev1 etc: from devices import dev1 and import dev1, and a splitting headache.

If your WSGI environment needs it (e.g. you can’t chdir or otherwise set a project root via mod_wsgi), you can prepend the project root, e.g. sys.path.insert(0, "c:/users/pvachal/documents/projekty/grp_exp_structure") in the WSGI entrypoint file but do not under any circumstance add a package (i.e. something that contains an __init__.py file).

Now that you’ve fixed that, you’ll need to change the absolute imports in devices/__init__.py to be relative, or to mention the package:

__all__ = ["dev1", "dev2", "dev3"]
from .dev1 import Dev1Cls  # or `from devices.dev1 ...`
from .dev2 import Dev2Cls
from .dev3 import Dev3Cls

Similarly, fix the import for webapp in the WSGI file:

from devices.webapp import Webapp
application = Webapp().app

and finally, if devices.webapp contains other imports that would have been absolute if devices was on the path, fix those up like above too.

In general, even outside of a WSGI context, you can now test that things are sane with a something.py in the grp_exp_structure directory:

import devices
from devices.webapp import Webapp

These imports should both work fine.

(Finally, as an aside, I would recommend to look at something other than Apache + mod_wsgi.)

Answered By: AKX
Categories: questions Tags: , , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.