ModuleNotFoundError - No module named 'main' when attempting to start service

21,585

Solution 1

By default, App Engine looks for an app variable in a file called main.py. You have two options: put your WSGI app where App Engine expects it to be, or define a custom entrypoint:

Put your WSGI app where App Engine expects it to be:

You can create a file called main.py that has an app variable which is simply imported and aliased from the correct location:

from demosite.wsgi import main as app

Adding a custom entrypoint:

From https://cloud.google.com/appengine/docs/standard/python3/config/appref:

entrypoint: Optional. The command that is executed when your app starts. For your app to receive HTTP requests, entrypoint should contain a command which starts a web server that listens on the port specified by the PORT environment variable. If you do not specify an entrypoint, App Engine will configure and start the Gunicorn webserver.

By default it's this:

entrypoint: gunicorn -b :$PORT main:app

You would need something like:

entrypoint: gunicorn -b :$PORT demosite.wsgi:main

See here for more details about application startup: https://cloud.google.com/appengine/docs/standard/python3/runtime#application_startup

Solution 2

Adding:

The main.py have to be in root of your application, where app.yaml is.

And the content, can to be, as well:

   from mysite.wsgi import application

   # App Engine by default looks for a main.py file at the root of the app
   # directory with a WSGI-compatible object called app.
   # This file imports the WSGI-compatible object of your Django app,
   # application from mysite/wsgi.py and renames it app so it is discoverable by
   # App Engine without additional configuration.
   # Alternatively, you can add a custom entrypoint field in your app.yaml:
   # entrypoint: gunicorn -b :$PORT mysite.wsgi
   app = application

Solution 3

Simply rename your main python app (for me it was app.py) to main.py. Google Cloud requires main.py to begin the process.

Share:
21,585

Related videos on Youtube

Marley
Author by

Marley

Updated on July 09, 2022

Comments

  • Marley
    Marley almost 2 years

    Context:

    • I created a Django application using Python 3.7.
    • I am (attempting) to use the 2nd generation Google App Engine standard environment.

    My application performs flawlessly when I run it via python manage.py runserver. Yet it comes to a sudden halt when I attempt to deploy it to Google App Engine.

    Traceback (most recent call last):
      File "/tmp/tmphgUsp3/lib/python3.7/site-packages/gunicorn/arbiter.py", line 583, in spawn_worker
        worker.init_process()
      File "/tmp/tmphgUsp3/lib/python3.7/site-packages/gunicorn/workers/base.py", line 129, in init_process
        self.load_wsgi()
      File "/tmp/tmphgUsp3/lib/python3.7/site-packages/gunicorn/workers/base.py", line 138, in load_wsgi
        self.wsgi = self.app.wsgi()
      File "/tmp/tmphgUsp3/lib/python3.7/site-packages/gunicorn/app/base.py", line 67, in wsgi
        self.callable = self.load()
      File "/tmp/tmphgUsp3/lib/python3.7/site-packages/gunicorn/app/wsgiapp.py", line 52, in load
        return self.load_wsgiapp()
      File "/tmp/tmphgUsp3/lib/python3.7/site-packages/gunicorn/app/wsgiapp.py", line 41, in load_wsgiapp
        return util.import_app(self.app_uri)
      File "/tmp/tmphgUsp3/lib/python3.7/site-packages/gunicorn/util.py", line 350, in import_app
        __import__(module)
    ModuleNotFoundError: No module named 'main'
    

    I've gone through numerous threads and I cannot find the problem. (For reference the dev_appserver.py emulator produces the same problem, which is a good thing).

    Following is my app.yaml

    runtime: python37
    env: standard
    
    handlers:
    - url: /static
      static_dir: static/
    - url: .*
      script: demosite.wsgi.main
    

    My wsgi.py file is located in the following path: demosite/wsgi.py and it's contents look like this:

    import os
    
    from django.core.wsgi import get_wsgi_application
    
    os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'demosite.settings')
    
    main = get_wsgi_application()
    

    My settings.py file:

    import os
    
    class AppSettings(object):
        GoogleCloudProject = os.getenv('GOOGLE_CLOUD_PROJECT')
    
    BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
    
    SECRET_KEY = 'say what?'
    
    DEBUG = True
    
    ALLOWED_HOSTS = [
        '*'
    ]
    
    
    INSTALLED_APPS = [
        'anchor.apps.AnchorConfig',
        'crispy_forms',
        'django.contrib.admin',
        'django.contrib.auth',
        'django.contrib.contenttypes',
        'django.contrib.sessions',
        'django.contrib.messages',
        'django.contrib.staticfiles',
    ]
    
    MIDDLEWARE = [
        'django.middleware.security.SecurityMiddleware',
        'django.contrib.sessions.middleware.SessionMiddleware',
        'django.middleware.common.CommonMiddleware',
        'django.middleware.csrf.CsrfViewMiddleware',
        'django.contrib.auth.middleware.AuthenticationMiddleware',
        'django.contrib.messages.middleware.MessageMiddleware',
        'django.middleware.clickjacking.XFrameOptionsMiddleware',
    ]
    
    ROOT_URLCONF = 'demosite.urls'
    
    TEMPLATES = [
        {
            'BACKEND': 'django.template.backends.django.DjangoTemplates',
            'DIRS': [],
            'APP_DIRS': True,
            'OPTIONS': {
                'context_processors': [
                    'django.template.context_processors.debug',
                    'django.template.context_processors.request',
                    'django.contrib.auth.context_processors.auth',
                    'django.contrib.messages.context_processors.messages',
                ],
            },
        },
    ]
    
    WSGI_APPLICATION = 'demosite.wsgi.main'
    
    try:
        import MySQLdb
    except ImportError:
        import pymysql
        pymysql.install_as_MySQLdb()
    
    
    if os.getenv('SERVER_SOFTWARE', '').startswith('Google App Engine'):
        DATABASES = {
            'default': {
                'ENGINE': 'django.db.backends.mysql',
                'NAME': 'webapp',
                'USER': 'aasdeytst',
                'PASSWORD': 'asdasygetasfasdfasd.',
                'HOST': 'asdgiuasfivaasd',
                'PORT': '3306'
            }
        }
    else:
        DATABASES = {
            'default': {
                'ENGINE': 'django.db.backends.mysql',
                'NAME': 'webapp',
                'USER': 'awthdsfhfdhdf',
                'PASSWORD': 'asdasdasdagwdatwt',
                'HOST': 'localhost',
                'PORT': '3306'
            }
        }
    
    AUTH_PASSWORD_VALIDATORS = [
        {
            'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
        },
        {
            'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
        },
        {
            'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
        },
        {
            'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
        },
    ]
    
    ANGUAGE_CODE = 'en-us'
    
    TIME_ZONE = 'UTC'
    
    USE_I18N = True
    
    USE_L10N = True
    
    USE_TZ = True
    
    STATIC_ROOT = 'static'
    STATIC_URL = '/static/'
    
    CRISPY_TEMPLATE_PACK = 'bootstrap4'
    
    LOGIN_REDIRECT_URL = 'index'
    LOGIN_URL = 'login'
    
    SESSION_EXPIRE_AT_BROWSER_CLOSE = False
    SESSION_COOKIE_AGE = 1800
    

    What am I missing, what am I doing wrong? I've spent close on 4 hours trying to figure this problem out to no avail.

  • Marley
    Marley over 5 years
    Dustin - thank you for your help. This was exactly what I needed (apart from having to juggle around STATIC_URL definitions after the fact).
  • Rohit Singh
    Rohit Singh almost 4 years
    This is exactly the problem in my case. I was trying to deploy Flask application o Google App Engine. I changed app.py --> main.py. Works like charm