Es gibt ein relativ neues (Oktober 2018-) Python-Webframework namens responder. Der Autor ist derjenige, der Anfragen usw. gestellt hat, und es scheint, dass es sich um einen Rahmen handelt, der den guten Punkten von Flask und Falcon entspricht. Als ich darüber nachdachte, eine einfache Webseite mit Python zu erstellen, erfuhr ich von Responder und war neugierig darauf. Deshalb entschied ich mich, sie zu verwenden. Soweit ich sehen kann, gab es keine Erklärung für Apache, daher werde ich meine eigene Konstruktionsmethode anstelle eines Memos veröffentlichen. (Bitte lassen Sie mich wissen, wenn Sie welche haben ...)
Es schien, dass Nginx einfacher zu erstellen war, aber ich entschied mich dafür, es so zu machen, wie es ist, weil es ein Server war, auf dem Apache ursprünglich installiert war.
Übrigens wird nur venv für das Python-Umgebungskonstruktionswerkzeug verwendet. Wenn Sie nach dem Erstellen einer Umgebung mit venv die folgende direnv-Einstellungsdatei auf das Arbeitsverzeichnis anwenden, wird sie gleichzeitig mit "cd" auf das Arbeitsverzeichnis "aktiviert", was praktisch ist.
.envrc
source <Vollständiger Pfad der venv-Aktivierungsdatei>
Ziel ist es, die folgenden Programme weltweit zu veröffentlichen und auszuführen. Das Programm selbst finden Sie im offiziellen Schnellstart.
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()
In diesem Fall wird beispielsweise, wenn Sie mit GET auf "/ world" zugreifen, diese als "Hello, world!" Angezeigt. Wenn Sie mit GET auf "/ testtesttest" zugreifen, wird sie als "Hello, testtest test!" Angezeigt.
Der Responder verfügt über einen integrierten Uvicorn-Server. Versuchen Sie zunächst, mit dem Responder (+ Uvicorn) zu beginnen.
$ 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!
Sie können sehen, dass der Server automatisch startet und nur durch Ausführen des Programms verbunden werden kann. Wenn Sie den Server herunterfahren, können Sie "Strg + C" wie geschrieben verwenden.
Offizielle Seite von Uvicorn Es scheint besser zu sein, Gunicorn für die Produktionsumgebung zu verwenden. Verschieben wir es also unter Bezugnahme auf die offiziellen Einstellungen. (Es ist schon eine Weile her, seit ich versucht habe, diesen Artikel zu schreiben, also keine Sorge, der Zeitstempel ist vor ein paar Monaten.)
$ 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!
Die Argumente beim Start von Gunicorn lauten ungefähr wie folgt.
---k uvicorn.workers.UvicornWorker
: Geben Sie Uvicorn als Arbeiterklasse an
--main: api
: Geben Sie das zu startende Modul an. Die Notation lautet "Modulname (Programmname): Variablenname von responder.API ()
"
Gunicorn-Einstellungselemente können auch aus der Einstellungsdatei gelesen werden. Es ist praktisch, später eine Einstellungsdatei zu haben, also erstellen Sie sie. Die im obigen Befehl verwendeten Argumente sind minimal. Erstellen Sie eine Einstellungsdatei, indem Sie hier den Speicherort der Protokolldatei hinzufügen.
gunicorn.py
import multiprocessing
import os
name = "gunicorn"
accesslog = "<Dateiname zum Schreiben des Zugriffsprotokolls>"
errorlog = "<Dateiname zum Schreiben des Fehlerprotokolls>"
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
Siehe Offizielle Dokumente für jeden Artikel. Der Einstellwert wird von dem von [Referenzstandort](# Referenzstandort) imitiert.
Verwenden Sie den folgenden Befehl, um diese Konfigurationsdatei anzuwenden und Gunicorn zu starten.
$ gunicorn --config gunicorn.py main:api
Richten Sie schließlich eine Verbindung über Apache ein. Wenn Sie mit http://example.com/ verbunden sind, auf dem Apache ausgeführt wird, konfigurieren Sie Gunicorn als Proxy für das wartende http: // localhost: 8000.
Erstellen Sie zunächst eine Konfigurationsdatei für den Reverse-Proxy.
/etc/apache2/conf-available/responder.conf
ProxyRequests Off
ProxyPass "/" "http://localhost:8000/"
ProxyPassReverse "/" "http://localhost:8000/"
Aktiviert die Konfigurationsdatei und die Proxy-bezogenen Module.
$ sudo a2enconf responder
$ sudo a2enmod proxy_http proxy
Laden Sie neu, nachdem Sie bestätigt haben, dass die Einstellungsdatei korrekt beschrieben wurde.
$ sudo apache2ctl configtest
Syntax OK
$ sudo systemctl reload apache2ctl
Um den automatischen Start zu vereinfachen, stellen Sie den Gunicorn-Start so ein, dass er von systemd verwaltet wird. Erstellen Sie zunächst eine Einstellungsdatei.
/etc/systemd/system/webapp.service
[Unit]
Description=gunicorn - responder
After=network.target
[Service]
User=www-data
Group=www-data
WorkingDirectory=<gunicorn.py und main.Vollständiger Pfad des Verzeichnisses, in dem sich py befindet>
ExecStart=<Voller Weg des Gunicorn> --config <gunicorn.voller Weg von py> main:api
ExecReload=/bin/kill -s HUP $MAINPID
ExecStop=/bin/kill -s TERM $MAINPID
PrivateTmp=true
[Install]
WantedBy=multi-user.target
Ich werde auch die Punkte erklären, die schwer zu verstehen sind.
--Dateiname: systemctl restart <set service name>
.
Stellen Sie den Dienst nach dem Erstellen so ein, dass er automatisch gestartet und gestartet wird.
$ sudo systemctl start webapp.service
$ sudo systemctl enable webapp.service
Stellen Sie für alle Fälle sicher, dass es richtig funktioniert.
$ sudo systemctl status webapp.service
● webapp.service - gunicorn - responder
Loaded: loaded (/etc/systemd/system/webapp.service; enabled; vendor preset: enable
Active: active (running)
(Unten weggelassen)
Sowohl der Start als auch der automatische Start waren erfolgreich.
Wenn die Einstellungen korrekt sind, sollten Sie in der Lage sein, eine Verbindung mit Curl oder einem Browser herzustellen.
$ curl http://example.com/world
Hello, world!
Aus irgendeinem Grund verschwindet der HTML-Header "Content-Type" beim Durchlaufen von Apache. (Es ist richtig angeschlossen, wenn der Server von Gunicorn aus gestartet wird. Geheimnisvolles Phänomen) Als vorläufige Maßnahme füge ich Code hinzu, der beim Zurückgeben einer Antwort "Content-Type: text / html; charset = UTF-8" erzwingt.
Übrigens möchte ich die Grammatik des Antwortenden aufschreiben, die ich persönlich nützlich / gegoogelt und schwer zu finden fand.
Es scheint mehr Routing (und Verarbeitung) zu geben als nur das Schreiben am Anfang.
Erstellen Sie eine Klasse+Richten Sie das Routing später gemeinsam ein.py
import responder
api = responder.API()
class Who:
def on_get(self, req, resp, *, who):
#Bei GET wird dieser Vorgang automatisch ausgeführt
resp.text = f"Hello, {who}!"
async def on_post(self, req, resp, *, who):
#Zum Zeitpunkt des POST wird dieser Vorgang automatisch ausgeführt
data = await req.media()
resp.text = f"{data}"
#Routing-Einstellungen
api.add_route("/{who}", Who)
if __name__ == '__main__':
api.run()
Ist der Schreibstil am Anfang wie Flask und der gerade geschriebene Schreibstil ist der Falcon-Stil?
Ich selbst habe in "Beschreibung mit on_get
usw. in der Klasse + Routing-Einstellung mit dem Dekorateur" geschrieben, aber vielleicht ist es eine schlechte Idee ...
Es kann verwendet werden, wenn Sie einen statischen Dateipfad definieren oder einen Prozess schreiben möchten, der viele Male wiederholt wird.
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()
#Filter hinzufügen
# v1.Für x
api.jinja_env.filters.update(
css = jinja_myfilter.css_filter,
html_list = jinja_myfilter.list_filter
)
# v2.Für x(2020/05/12 Nachtrag)
# (Weil es einen Unterstrich gibt_env scheint als interner Wert behandelt zu werden,
#Ich konnte keine andere Möglichkeit finden, es zu spezifizieren, indem ich mir die Quelle ansah ...)
api.templates._env.filters.update(
css = jinja_myfilter.css_filter,
html_list = jinja_myfilter.list_filter
)
@api.route("/")
def greet_world(req, resp):
param = ["Gegenstand 1", "Punkt 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 }}">
<!--Es wird von Jinja2 verarbeitet und wird wie folgt
<link rel="stylesheet" type="text/css" href="./static/css/form.css">
-->
{% autoescape false %}
{{ param | html_list }}
{% endautoescape %}
<!--Es wird von Jinja2 verarbeitet und wird wie folgt
<ul>
<li>Gegenstand 1</li>
<li>Punkt 2</li>
</ul>
-->
Wenn eine Zeichenfolge zurückgegeben wird, die ein HTML-Tag enthält, funktioniert die automatische Escape-Funktion, sofern sie nicht in "{% autoescape false%} to {% endautoescape%}" eingeschlossen ist. Wenn es sich bei den von Ihnen übergebenen Parametern jedoch um Benutzereingaben handelt, werden die Parameter natürlich ohne Escapezeichen ausgegeben. Seien Sie also vorsichtig. Ist es sicher, es mit html.escape ()
usw. im Filter zu verarbeiten?
Wie man Responder mit Uvicorn oder Gunicorn bereitstellt - ich möchte über Technologie und Ausweichen sprechen Für eine Einführung in Python Responder ... Voruntersuchungen - Qiita Anwendung mit Django + Nginx + Gunicorn | WEB Curtain Call starten [[1st] Lassen Sie uns eine Webanwendung für maschinelles Lernen mit Responder und Keras erstellen. [Übersichtserstellung] - Light Code Co., Ltd.](https://rightcode.co.jp/blog/information-technology/responder- keras-make-machine-learning-web-appsz9) Jinja2s benutzerdefinierter Filter zum Konvertieren von Zeilenumbrüchen in --- Ein Tagebuch zur Deprogrammierung von Anfängern mit Google App Engine + Python
Recommended Posts