Obsluhovat to waitressem, ne vývojovým serverem Flasku
Flask pod pěkně naformátovanou úvodní hlášku vysypal červené varování, že tohle není produkční server. Waitress je čistě pythonní, takže ho PyInstaller zabalí bez řečí, a osm vláken pobere telefony u stolu i tabuli, která se doptává každé dvě vteřiny. Cestou se ukázalo, že hláška se nikdy nedostala do přesměrovaného výstupu: mimo konzoli drží Python výstup v bloku a pouští ho, až program skončí — jenže server neskončí. Zkouška binárky u Gitey si logovala do souboru a pak ho vypisovala, takže celou dobu tiskla prázdno. Řeší to řádkové bufferování v console.utf8(), kam to patří vedle té kódové stránky.
This commit is contained in:
1 parent
e3d56f4c22
commit
33e8582079
4 files changed
+39
-5
No files matched your search
@@ -106,6 +106,10 @@ schématu ještě nepsala, se poznají podle nuly a orazítkují se. Databázi
|
||||
založenou novější verzí počitadla appka odmítne otevřít, místo aby ji tiše
|
||||
rozbila.
|
||||
|
||||
Obsluhuje to `waitress` — čistě pythonní WSGI server, který se zabalí do
|
||||
binárky stejně snadno jako zbytek. Vestavěný server Flasku by pod úvodní
|
||||
hlášku vysypal varování, že takhle se to nemá, a měl by pravdu.
|
||||
|
||||
Počítá se s domácí sítí — appka nemá přihlašování a kdokoli na stejné WiFi
|
||||
může zapisovat.
|
||||
|
||||
|
||||
+10
-3
@@ -1,10 +1,10 @@
|
||||
"""Aby čeština prošla i tam, kde konzole čeká něco jiného."""
|
||||
"""Aby výstup prošel i tam, kde ho nikdo nečeká na konzoli."""
|
||||
|
||||
import sys
|
||||
|
||||
|
||||
def utf8() -> None:
|
||||
"""Přepne standardní výstup na UTF-8.
|
||||
"""Přepne standardní výstup na UTF-8 a na řádkové bufferování.
|
||||
|
||||
Windows sahá po historické kódové stránce (cp1252, cp852) všude, kde
|
||||
výstup není konzole — přesměrovaný do souboru, puštěný ze skriptu, ve
|
||||
@@ -14,7 +14,14 @@ def utf8() -> None:
|
||||
Na konzoli i na ostatních systémech je UTF-8 dávno výchozí a tohle je
|
||||
tam prázdná operace. `errors="replace"` je pojistka pro zbylé případy:
|
||||
rozsypaný háček je pořád lepší než spadlý server.
|
||||
|
||||
Řádkové bufferování řeší druhou půlku téhož problému. Mimo konzoli
|
||||
Python drží výstup v bloku a pouští ho, až se naplní nebo až program
|
||||
skončí — jenže server neskončí, ten běží. Kdo si ho pustí na pozadí
|
||||
s výpisem do souboru, našel by tam prázdno; přesně to dělá zkouška
|
||||
binárky v CI. Pár řádek hlášky za to bufferovat nemá cenu.
|
||||
"""
|
||||
for stream in (sys.stdout, sys.stderr):
|
||||
if hasattr(stream, "reconfigure"):
|
||||
stream.reconfigure(encoding="utf-8", errors="replace")
|
||||
stream.reconfigure(encoding="utf-8", errors="replace",
|
||||
line_buffering=True)
|
||||
+18
-1
@@ -9,10 +9,12 @@ class Proud:
|
||||
def __init__(self):
|
||||
self.encoding = "cp1252"
|
||||
self.errors = "strict"
|
||||
self.line_buffering = False
|
||||
|
||||
def reconfigure(self, encoding, errors):
|
||||
def reconfigure(self, encoding, errors, line_buffering=False):
|
||||
self.encoding = encoding
|
||||
self.errors = errors
|
||||
self.line_buffering = line_buffering
|
||||
|
||||
|
||||
def test_vystup_se_prepne_na_utf8(monkeypatch):
|
||||
@@ -24,6 +26,7 @@ def test_vystup_se_prepne_na_utf8(monkeypatch):
|
||||
|
||||
assert (out.encoding, out.errors) == ("utf-8", "replace")
|
||||
assert (err.encoding, err.errors) == ("utf-8", "replace")
|
||||
assert out.line_buffering and err.line_buffering
|
||||
|
||||
|
||||
def test_cestina_projde_i_pres_cp1252(monkeypatch):
|
||||
@@ -46,3 +49,17 @@ def test_proud_bez_reconfigure_se_prezije(monkeypatch):
|
||||
monkeypatch.setattr(console.sys, "stderr", object())
|
||||
|
||||
console.utf8()
|
||||
|
||||
|
||||
def test_hlaska_je_v_souboru_hned(tmp_path, monkeypatch):
|
||||
"""Server běží dál, takže na vyprázdnění bufferu při konci se čekat nedá."""
|
||||
cesta = tmp_path / "server.log"
|
||||
with cesta.open("w", encoding="utf-8") as soubor:
|
||||
monkeypatch.setattr(console.sys, "stdout", soubor)
|
||||
monkeypatch.setattr(console.sys, "stderr", soubor)
|
||||
|
||||
console.utf8()
|
||||
print("Počitadlo je dostupné na:", file=console.sys.stdout)
|
||||
|
||||
# Bez zavření souboru — přesně jako u běžícího serveru.
|
||||
assert "Počitadlo je dostupné" in cesta.read_text(encoding="utf-8")
|
||||
@@ -17,6 +17,7 @@ import qrcode
|
||||
from flask import (Flask, abort, g, redirect, render_template, request,
|
||||
url_for)
|
||||
from markupsafe import Markup, escape
|
||||
from waitress import serve
|
||||
|
||||
import console
|
||||
import net
|
||||
@@ -353,4 +354,9 @@ if __name__ == "__main__":
|
||||
sys.exit(0)
|
||||
|
||||
announce()
|
||||
app.run(host="0.0.0.0", port=PORT, threaded=True)
|
||||
|
||||
# Ne vestavěný server Flasku: ten pod úvodní hlášku vysype červené
|
||||
# varování, že takhle se to nemá, a má pravdu. Waitress je čistě
|
||||
# pythonní, takže se zabalí do binárky bez řečí, a osm vláken pobere
|
||||
# telefony u stolu i tabuli, která se doptává každé dvě vteřiny.
|
||||
serve(app, host="0.0.0.0", port=PORT, threads=8)
|
||||
Reference in new issue
Block a user