Il existe un framework Web Python relativement nouveau (octobre 2018-) appelé responder. L'auteur est celui qui a fait des requêtes etc., et il semble que ce soit un framework comme les bons points de Flask et Falcon. Quand j'ai pensé à créer une simple page Web avec Python, j'ai découvert le répondeur et j'étais curieux à ce sujet, alors j'ai décidé de l'utiliser. Pour autant que je sache, il n'y avait aucune explication en utilisant Apache, donc je publierai ma propre méthode de construction au lieu d'un mémo. (S'il vous plaît laissez-moi savoir si vous en avez ...)
Il semblait que Nginx était plus facile à construire, mais j'ai décidé de le faire tel quel parce que c'était un serveur sur lequel Apache était installé à l'origine.
À propos, seul venv est utilisé pour l'outil de construction d'environnement Python. Après avoir créé un environnement avec venv, appliquer le fichier de paramétrage direnv suivant au répertoire de travail est pratique car il sera «activé» en même temps que «cd» dans le répertoire de travail.
.envrc
source <Chemin complet du fichier d'activation de venv>
L'objectif est de publier et d'exécuter les programmes suivants à l'échelle mondiale. Pour le programme lui-même, rendez-vous sur le site officiel Quick Start.
main.py
import responder
api = responder.API()
@api.route("/{who}")
def greet_world(req, resp, *, who):
resp.text = f"Hello, {who}!"
if __name__ == '__main__':
api.run()
Dans ce cas, par exemple, si vous accédez à / world
avec GET, vous verrez Hello, world!
, Ou si vous accédez à / testtesttest
avec GET, vous verrez Hello, test test!
.
Le répondeur a Uvicorn intégré en tant que serveur intégré. Tout d'abord, essayez de commencer par responder (+ Uvicorn).
$ python main.py
INFO: Started server process [693]
INFO: Waiting for application startup.
INFO: Uvicorn running on http://127.0.0.1:5042 (Press CTRL+C to quit)
$ curl http://127.0.0.1:5042/world
Hello, world!
Vous pouvez voir que le serveur démarre automatiquement et peut être connecté simplement en exécutant le programme.
Lorsque vous arrêtez le serveur, vous pouvez utiliser Ctrl + C
comme écrit.
Page officielle d'Uvicorn Il semble qu'il soit préférable d'utiliser Gunicorn pour l'environnement de production, alors déplaçons-le en se référant aux paramètres officiels. (Cela fait un moment que j'ai essayé d'écrire cet article, alors ne vous inquiétez pas, l'horodatage date d'il y a quelques mois.)
$ pip install gunicorn
$ gunicorn -k uvicorn.workers.UvicornWorker main:api
[2019-10-31 09:39:11 +0900] [1227] [INFO] Starting gunicorn 19.9.0
[2019-10-31 09:39:11 +0900] [1227] [INFO] Listening at: http://127.0.0.1:8000 (1227)
[2019-10-31 09:39:11 +0900] [1227] [INFO] Using worker: uvicorn.workers.UvicornWorker
[2019-10-31 09:39:11 +0900] [1230] [INFO] Booting worker with pid: 1230
[2019-10-31 09:39:12 +0900] [1230] [INFO] Started server process [1230]
[2019-10-31 09:39:12 +0900] [1230] [INFO] Waiting for application startup.
$ curl http://127.0.0.1:8000/world
Hello, world!
Les arguments lors du lancement de Gunicorn sont à peu près les suivants.
---k uvicorn.workers.UvicornWorker
: Spécifiez Uvicorn comme classe de travail
--main: api
: Spécifiez le module à démarrer. La notation est "nom du module (nom du programme): nom de variable de responder.API ()
"
Les éléments de paramétrage Gunicorn peuvent également être lus à partir du fichier de paramétrage. Il est pratique d'avoir un fichier de paramètres plus tard, alors créez-le. Les arguments utilisés dans la commande ci-dessus sont minimes. Créez un fichier de paramètres en ajoutant ici l'emplacement d'enregistrement du fichier journal.
gunicorn.py
import multiprocessing
import os
name = "gunicorn"
accesslog = "<Nom de fichier pour écrire le journal d'accès>"
errorlog = "<Nom de fichier pour écrire le journal des erreurs>"
bind = "localhost:8000"
worker_class = "uvicorn.workers.UvicornWorker"
workers = multiprocessing.cpu_count() * 2 + 1
worker_connections = 1024
backlog = 2048
max_requests = 5120
timeout = 120
keepalive = 2
user = "www-data"
group = "www-data"
debug = os.environ.get("DEBUG", "false") == "true"
reload = debug
preload_app = False
daemon = False
Voir Documents officiels pour chaque élément. La valeur du paramètre est imitée de celle de [Site de référence](# site de référence).
Pour appliquer ce fichier de configuration et lancer Gunicorn, utilisez la commande suivante.
$ gunicorn --config gunicorn.py main:api
Enfin, configurez-vous pour vous connecter via Apache. Une fois connecté à http://example.com/ sur lequel Apache est en cours d'exécution, configurez Gunicorn pour qu'il utilise le proxy vers http: // localhost: 8000.
Commencez par créer un fichier de configuration pour le proxy inverse.
/etc/apache2/conf-available/responder.conf
ProxyRequests Off
ProxyPass "/" "http://localhost:8000/"
ProxyPassReverse "/" "http://localhost:8000/"
Activez le fichier de configuration et les modules liés au proxy.
$ sudo a2enconf responder
$ sudo a2enmod proxy_http proxy
Rechargez après avoir vérifié que le fichier de paramètres est correctement décrit.
$ sudo apache2ctl configtest
Syntax OK
$ sudo systemctl reload apache2ctl
Pour faciliter le démarrage automatique, configurez le démarrage de Gunicorn pour qu'il soit géré par systemd. Commencez par créer un fichier de paramètres.
/etc/systemd/system/webapp.service
[Unit]
Description=gunicorn - responder
After=network.target
[Service]
User=www-data
Group=www-data
WorkingDirectory=<gunicorn.py et main.Chemin complet du répertoire où se trouve py>
ExecStart=<Chemin complet de Gunicorn> --config <gunicorn.chemin complet de py> main:api
ExecReload=/bin/kill -s HUP $MAINPID
ExecStop=/bin/kill -s TERM $MAINPID
PrivateTmp=true
[Install]
WantedBy=multi-user.target
J'expliquerai également les éléments difficiles à comprendre.
--Nom de fichier:
Après la création, configurez le service pour qu'il démarre et démarre automatiquement.
$ sudo systemctl start webapp.service
$ sudo systemctl enable webapp.service
Juste au cas où, assurez-vous que cela fonctionne correctement.
$ sudo systemctl status webapp.service
● webapp.service - gunicorn - responder
Loaded: loaded (/etc/systemd/system/webapp.service; enabled; vendor preset: enable
Active: active (running)
(Omis ci-dessous)
Le démarrage et le démarrage automatique ont réussi.
Si les paramètres sont corrects, vous devriez pouvoir vous connecter avec curl ou un navigateur.
$ curl http://example.com/world
Hello, world!
Pour une raison quelconque, l'en-tête html Content-Type
disparaît lors du passage par Apache.
(Il est correctement attaché lorsque le serveur est démarré depuis Gunicorn. Phénomène mystérieux)
En guise de mesure provisoire, j'ajoute du code qui force Content-Type: text / html; charset = UTF-8
lors du renvoi d'une réponse.
En passant, j'aimerais écrire la grammaire du répondeur que j'ai personnellement trouvé utile / googlé et difficile à trouver.
Il semble y avoir plus de routage (et de traitement) que d'écrire simplement au début.
Créer une classe+Configurer le routage collectivement plus tard.py
import responder
api = responder.API()
class Who:
def on_get(self, req, resp, *, who):
#Lorsque GET, ce processus se fait automatiquement
resp.text = f"Hello, {who}!"
async def on_post(self, req, resp, *, who):
#Au moment du POST, ce processus se fait automatiquement
data = await req.media()
resp.text = f"{data}"
#Paramètres de routage
api.add_route("/{who}", Who)
if __name__ == '__main__':
api.run()
Le style d'écriture au début est-il semblable à Flask, et le style d'écriture qui vient d'être écrit est le style Falcon? J'ai écrit dans "Description en utilisant ʻon_get` etc. dans la classe + Paramètres de routage avec décorateur", mais c'est peut-être une mauvaise idée ...
Il peut être utilisé lorsque vous souhaitez définir un chemin de fichier statique ou écrire un processus répété plusieurs fois.
jinja_myfilter.py
def css_filter(path):
return f"./static/css/{path}"
def list_filter(my_list):
return_text = "<ul>\n"
for l in my_list:
return_text += f"<li> {l} </li>\n"
return_text += "</ul>"
return return_text
main.py
import responder
import jinja_myfilter
api = responder.API()
#Ajouter un filtre
# v1.Pour x
api.jinja_env.filters.update(
css = jinja_myfilter.css_filter,
html_list = jinja_myfilter.list_filter
)
# v2.Pour x(2020/05/12 Addendum)
# (Parce qu'il y a un trait de soulignement_env semble être traité comme une valeur interne,
#Je n'ai pas trouvé d'autre moyen de le spécifier en regardant la source ...)
api.templates._env.filters.update(
css = jinja_myfilter.css_filter,
html_list = jinja_myfilter.list_filter
)
@api.route("/")
def greet_world(req, resp):
param = ["Objet 1", "Point 2"]
resp.content = api.template("index.html", param=param)
if __name__ == '__main__':
api.run()
index.html
<link rel="stylesheet" type="text/css" href="{{ 'form.css' | css }}">
<!--Il est traité par Jinja2 et devient comme suit
<link rel="stylesheet" type="text/css" href="./static/css/form.css">
-->
{% autoescape false %}
{{ param | html_list }}
{% endautoescape %}
<!--Il est traité par Jinja2 et devient comme suit
<ul>
<li>Objet 1</li>
<li>Point 2</li>
</ul>
-->
Si une chaîne de caractères contenant une balise html est renvoyée, l'échappement automatique fonctionnera à moins qu'il ne soit inclus entre {% autoescape false%} à {% endautoescape%}
. Cependant, si les paramètres que vous passez sont des entrées utilisateur, les paramètres seront bien sûr sortis sans être échappés, alors soyez prudent. Est-il sûr de le traiter en utilisant html.escape ()
etc. dans le filtre?
Comment déployer Responder avec Uvicorn ou Gunicorn - Je veux parler de technologie et de bodge Pour une introduction au répondeur Python ... Recherche préliminaire --Qiita Lancer l'application avec Django + Nginx + Gunicorn | WEB Curtain Call [[1er] Créons une application Web d'apprentissage automatique en utilisant Responder et Keras [Création d'une vue d'ensemble] - Light Code Co., Ltd.](https://rightcode.co.jp/blog/information-technology/responder- keras-make-machine-learning-web-appsz9) Filtre personnalisé de Jinja2 pour convertir les sauts de ligne en --- Un journal destiné à déprogrammer les débutants avec Google App Engine + Python
Recommended Posts