Le contexte:
Mon application fonctionne parfaitement lorsque je l'exécute via python manage.py runserver
. Pourtant, il s'arrête soudainement lorsque j'essaie de le déployer sur 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'
J'ai parcouru de nombreux threads et je ne trouve pas le problème. (Pour référence, le dev_appserver.py
l'émulateur produit le même problème, ce qui est une bonne chose).
Voici mon app.yaml
runtime: python37
env: standard
handlers:
- url: /static
static_dir: static/
- url: .*
script: demosite.wsgi.main
Ma wsgi.py
le fichier se trouve dans le chemin suivant: demosite/wsgi.py
et son contenu ressemble à ceci:
import os
from Django.core.wsgi import get_wsgi_application
os.environ.setdefault('Django_SETTINGS_MODULE', 'demosite.settings')
main = get_wsgi_application()
Ma settings.py
fichier:
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
Qu'est-ce que je manque, que fais-je de mal? J'ai passé près de 4 heures à essayer de résoudre ce problème en vain.
Par défaut, App Engine recherche une variable app
dans un fichier appelé main.py
. Vous avez deux options: placez votre application WSGI là où App Engine l'attend, ou définissez un point d'entrée personnalisé:
Vous pouvez créer un fichier appelé main.py
qui a une variable app
qui est simplement importée et aliasée de l'emplacement correct:
from demosite.wsgi import main as app
De https://cloud.google.com/appengine/docs/standard/python3/config/appref :
entrypoint
: facultatif. La commande qui est exécutée au démarrage de votre application. Pour que votre application reçoive des requêtes HTTP,entrypoint
doit contenir une commande qui démarre un serveur Web qui écoute sur le port spécifié par la variable d'environnement PORT. Si vous ne spécifiez pas deentrypoint
, App Engine configurera et démarrera le serveur Web Gunicorn.
Par défaut, c'est ceci:
entrypoint: gunicorn -b :$PORT main:app
Vous auriez besoin de quelque chose comme:
entrypoint: gunicorn -b :$PORT demosite.wsgi:main
Voir ici pour plus de détails sur le démarrage de l'application: https://cloud.google.com/appengine/docs/standard/python3/runtime#application_startup
Ajouter:
Le fichier main.py doit se trouver à la racine de votre application, où se trouve app.yaml.
Et le contenu peut aussi être:
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