Seite 1 von 1
Webseite print(): Umlaute & Backslashes
Verfasst: Freitag 26. Juli 2019, 09:34
von dd0815
Hallo Python-Gemeinde,
ich habe ein kleines Problem: Ich generiere mit Python eine Webseite und gebe sie mit print() aus. Zum einen werden Umlaute nicht richtig dargestellt und zum anderen verschwinden Backslashes, so dass der Javascript-Code fehlerhaft wird. In der Quelltext-Datei steht alles richtig, nur wenn man im Quelltext des Browsern schaut, ist es eben falsch. Irgendwo geht bei der Übergabe zum Browser das Utf-8 verloren.
Hier etwas Quelltext (ist aus einem Beispielprojekt aus dem Netz für ein Kontextmenü (Javascript)):
Code: Alles auswählen
response += """
<script>
...
output += '<tr><td onclick="cmenu = false;">Immer normales Kontextmenü<\/td><\/tr>';
output += '<tr><td onclick="setTimeout(function () {cmenu = null;}, 1);">Einmal normales Kontextmenü<\/td><\/tr>';
output += '<tr><td onclick="transparent(\''+element.id+'\', \'-\');">Transparenter<\/td><\/tr>';
if (get_opacity(element) < 1) {
output += '<tr><td onclick="transparent(\''+element.id+'\', \'+\');">Weniger Transparent<\/td><\/tr>';
}
...
</script>"""
Daraus wird im Webseiten-Quelltext:
Code: Alles auswählen
output += '<tr><td onclick="cmenu = false;">Immer normales Kontextmen�<\/td><\/tr>';
output += '<tr><td onclick="setTimeout(function () {cmenu = null;}, 1);">Einmal normales Kontextmen�<\/td><\/tr>';
output += '<tr><td onclick="transparent(''+element.id+'', '-');">Transparenter<\/td><\/tr>';
if (get_opacity(element) < 1) {
output += '<tr><td onclick="transparent(''+element.id+'', '+');">Weniger Transparent<\/td><\/tr>';
}
Interessant ist, dass nur die Backslashs verschwinden, die innerhalb doppelter Anführungszeichen stehen (innerhalb des Blockes mit den 3 Anführungszeichen). Es ist zwar etwas umständlich und eigentlich unschön, nur diese Backslashs zu escapen:
aber es wird mir wohl nichts anderes übrig bleiben. Wie macht Ihr das?
Sämtliche im Netz aufgeschnappten Versuche der Utf-8 Konvertierung schlugen fehl (es darf zu Eurer Erheiterung dienen - seht es mir nach, bin Python-Anfänger):
Code: Alles auswählen
print (response)
#print(repr(response))
#print(response % vars())
#print(response).encode('utf-8')
#response = unicode(response, 'UTF-8')
#print(response).decode('raw-unicode-escape').encode('utf-8')
#print(response.encode('utf-8'))
#print(response.encode('UTF-8'))
Könnt Ihr mich vielleicht etwas in die richtige Richtung schubsen?
Habe das noch gefunden:
Die häufigsten Fehler sind als ISO-8859-1, -15 oder Windows-1252 deklarierte Daten, die aber tatsächlich UTF-8-kodiert wurden oder umgekehrt. Dies äußert sich dann darin, dass beispielsweise aus einem ä die Zeichenfolge À wird – das Zeichen ä wird in UTF-8 in zwei Bytes kodiert, was in Ein-Byte-Codierungen zwei Zeichen entspricht. Tritt hingegen das Zeichen � auf, werden Daten in einer Ein-Byte-Codierung (ISO-8859-X, Windows-1252) als UTF-8 deklariert und interpretiert – nicht alle Byte-Kombinationen aus Ein-Einbyte-Codierungen sind gültiges UTF-8 und das wird durch das spezielle Zeichen � kenntlich gemacht.
In beiden Fällen muss nach der abweichenden Zeichencodierungs-Deklaration (s. o.) im System gesucht werden und an die tatsächliche angepasst werden – wobei ein Umstieg auf UTF-8 bevorzugt werden sollte.
Leider weiß ich dadurch nicht, was ich wo umstellen muss, Ihr vielleicht?
Viele Grüße,
dd0815
Python: 3.7
Webserver: Apache (Xampp)
Re: Webseite print(): Umlaute & Backslashes
Verfasst: Freitag 26. Juli 2019, 09:57
von __deets__
Man macht das so nicht. Man benutzt ein Rahmenwerk und eine Template-Engine. Und liefert JavaScript als eigene Datei aus. Und schreibt keine Event Handler in die Tags. Sondern benutzt Dinge wie jQuery oder andere JS Bibliotheken, um zb per ID Code an Tags zu binden. Und neben besserer Wartbarkeit (weil nicht alles ineinander verschränkt ist) und leichterer Programmierung (weil zB Unterschiede in Browsern abstrahiert sind) löst das auch solche Probleme.
Re: Webseite print(): Umlaute & Backslashes
Verfasst: Freitag 26. Juli 2019, 10:03
von Sirius3
Entscheidend ist, was Du mit `response` weiter machst. Dort wird es irgendwo dann anders codiert, als es die Webseite denkt, dass sie ausgeliefert wurde.
Und \ ist halt sowohl in Python als auch in Javascript, als auch in den meisten anderen Sprachen, ein Escapezeichen. Wenn man das nicht als Escapezeichen behandeln will, muß man es escapen.
Aber statt HTML oder Javascript direkt in Python mit + zusammenzustückeln, nimmt man eine Template-Engine.
@__deets__: jQuery ist heutzutage (fast immer) unnötig. Javascript und die aktuellen Browser sind so standardisiert, dass man eigentlich alles mit Boardmitteln machen kann.
Re: Webseite print(): Umlaute & Backslashes
Verfasst: Freitag 26. Juli 2019, 10:04
von Jankie
Um die Backslashes zu behalten benutzt man raw strings.
also
Ob das allerdings deinen Fehler behebt kann ich leider nicht sagen, dafür kenne ich mich zu wenig aus.
Re: Webseite print(): Umlaute & Backslashes
Verfasst: Freitag 26. Juli 2019, 10:06
von __deets__
@Sirius3: habe ich auch gerade entdeckt
http://vanilla-js.com/
Der Rat bleibt davon aber unberührt - auch in purem JS schreibt man nichts in die Tags selbst. Sondern holt sie per ID etc.
Oder geht einen Schritt weiter & benutzt vue.js oder oder oder.
Re: Webseite print(): Umlaute & Backslashes
Verfasst: Freitag 26. Juli 2019, 10:16
von dd0815
@__deets__:
wenn ich etwas Neues mache, dann probiere ich gerne Sachen direkt aus und ohne Abhängigkeiten. Es mag sein, später mal Frameworks mit Template-Engine zu benutzen (habe mich da auch angefangen einzulesen), aber jetzt grade ist das nicht die Frage... Prinzipiell sollte doch durchgehend alles utf-8 sein...
@ Sirius3:
Na zum Schluß der Zusammenstückelung wirds halt ausgegeben
keine Konvertierungen dazwischen.
@ Jankie:
probiere ich mal aus...
Wo wir schon mal dabei sein: Wie sind Eure Erfahrungen, wenn man später mal die Frameworks bei einem Webhoster installieren lassen muss? Man kommt ja selbst nicht an das System ran, um mittels pip die Sachen zu installieren.
Re: Webseite print(): Umlaute & Backslashes
Verfasst: Freitag 26. Juli 2019, 10:22
von dd0815
@ Jankie:
Mit
Code: Alles auswählen
response += r"""
<script>
var cursorx, cursory, cmenu;
cmenu = true;
...
ist zumindest das Backslash-Problem gelöst - vielen Dank...
Re: Webseite print(): Umlaute & Backslashes
Verfasst: Freitag 26. Juli 2019, 10:30
von dd0815
@__deets__:
...auch in purem JS schreibt man nichts in die Tags selbst. Sondern holt sie per ID etc.
Was genau meinst Du damit? Bitte mal ein Link oder ein minimal-Beispiel oder ein google-verwertbaren Suchbegriff... Ich wäre schon extrem dran interessiert, wie man Python-Webapplikationen sinnvoll strukturiert und aufteilt (wie gesagt, erstmal zum Verständnis jenseits aller Frameworks)...
Re: Webseite print(): Umlaute & Backslashes
Verfasst: Freitag 26. Juli 2019, 10:55
von Sirius3
@dd0815: das läßt zusätzlich befürchten dass Du CGI benutzt. Dann wird die Ausgabe so encodiert, wie Python meint, dass Dein Terminal das braucht. Apache scheint etwas anders zu meinen, teilt das aber Python nicht mit.
bottle.py ist eine einzige Datei als Abhängigkeit, kann also überall ohne Probleme mitgeliefert werden. Du tust Dir keinen Gefallen, alles von Grund auf selbst machen zu wollen. Du merkst ja, dass Du in Probleme hineinstolperst, die Du nicht so einfach lösen kannst, und dass sind nur die Probleme, die Dir jetzt auffallen. Gravierende Sicherheitsprobleme, die Du aufreißt, weil Du ohne Template-Engine Injektionlücken nicht berücksichtigst, seien hier noch gar nicht erwähnt.
Und weil Du scheinbar nicht nur in Python Javascript-Code zusammenstückelst, sondern diesen Javascript-Code auch noch benutzt, um damit HTML zusammen zu stückeln, quadrieren sich Deine Probleme.
Re: Webseite print(): Umlaute & Backslashes
Verfasst: Freitag 26. Juli 2019, 10:58
von dd0815
Mein Standard-Ausgabe-Encoding ist (Trommelwirbel für die große Überraschung):
nicht utf-8. Nur noch finden, wie man es ändert
Re: Webseite print(): Umlaute & Backslashes
Verfasst: Freitag 26. Juli 2019, 11:04
von __blackjack__
@dd0815: Es macht wirklich keinen Sinn sich damit herum zu schlagen. Nimm ein Rahmenwerk und eine Template-Engine und trenne das alles sauber. Du hast jetzt kennengelernt wie blöd das alles ohne ist, mehr sinnvolles kann man dabei nicht wirklich lernen. Mach es richtig. Rahmenwerke gibt's ja auch in klein, so ab `bottle` aufwärts. Bottle ist *eine* Python-Datei, die kann man notfalls auch direkt mit in den gleichen Ordner packen wenn man sie nicht installieren kann oder will. Da ist zwar auch schon eine Template-Engine mit enthalten, aber ich persönlich verwende dann doch lieber Jinja2.
Mit den ``onclick=…`` ist gemeint das man die in JavaScript eigentlich nicht benutzt sondern den Elementen ``id``- oder ``class``-Attribute verpasst und über die dann per JavaScript Rückrufe für Ereignisse an die Elemente bindet. Ich persönlich bin an dieser Stelle kein grosser Fan von “Vanilla JS” weil das mit JQuery IMHO alles einfacher und kürzer und IMO auch konsistenter geht. Kann natürlich auch jahrelange Gewohnheit sein.
Den Menüteil würde ich nicht als Quelltext in JavaScript zusammenstückeln, sondern als <script> oder ”hidden” im HTML definieren und dann bei Bedarf entweder anzeigen, oder klonen und den Klon anzeigen. Je nach dem wie statisch der Inhalt ist.
In aller Regel hat JavaScript nichts im HTML verloren, sondern steht in *.js-Dateien die in <script>-Tags eingebunden werden.
Re: Webseite print(): Umlaute & Backslashes
Verfasst: Freitag 26. Juli 2019, 11:12
von dd0815
@Sirius3:
Also ich weiß gar nicht ob ich CGI benutze, explizit habe ich das jedenfalls nirgendwo angegeben. Keine Ahnung, wie das Python intern regelt. Ich erstelle eine Webseite und gebe Sie mit Print() aus. Im Browser rufe ich dann das Programm *.py direkt auf.
Wie gesagt, ich spiele grade nur rum. Bis jetzt habe ich ein HTML-Grid-Layout und eine Datenbankabfrage, die via Ajax auf der Webseite nachgeladen wird sowie nun endlich ein funktionierendes Kontextmenü...
Ich kann keine Entscheidungen über ein Framework treffen (zumal es endlos viele gibt), wenn ich keine Ahnung habe worum es eigentlich geht - deswegen die Spielerei... Ja, es geht später mal um eine Webseite, die viele firmeninterne Datenquellen bündeln soll (mehrere Datenbanken, aber auch CSV-Dateien u.ä.). Wie man SQL-Injection verhindert, habe ich auch irgendwo gelesen und mir vermutlich ein Link gemacht.
Gern schaue ich mir später mal bottle an...
Re: Webseite print(): Umlaute & Backslashes
Verfasst: Freitag 26. Juli 2019, 11:22
von dd0815
Die Lösung (zumindest ab Python 3.7):
Re: Webseite print(): Umlaute & Backslashes
Verfasst: Freitag 26. Juli 2019, 11:46
von __blackjack__
@dd0815: Dann verwendest Du CGI – als einziger Mensch sein mindestens 20+ Jahren.
Webanwendungen werden in Python per WSGI bereitgestellt. Alles andere macht keinen Sinn weil nicht praxisrelevant. Selbst wenn einem am Ende nur CGI zur Verfügung stehen sollte, schreibt man die Webanwendung gegen WSGI, denn das kann man, wenn es wirklich gar nicht anders geht auch als CGI an einen Webserver anbinden.
Aber selbst WSGI ist zu wenig um damit sinnvoll arbeiten zu können. Da hat man dann mindestens `werkzeug` als Bibliothek mit kleinen Helfern die man nicht selbst erfinden möchte. Den Debugger von `werkzeug` würde ich auch um alles in der Welt nicht missen wollen.
Es gibt nicht endlos viele Webrahmenwerke. Es gibt Bottle und Flask als Mikrorahmenwerke und es gibt Django als eierlegende Wollmilchsau. Alles andere sind eher Nischenprodukte. Die müssen deswegen nicht schlecht sein, aber da muss man sich dann wirklich ein bisschen Zeit nehmen und schauen warum man die, statt der Standardlösungen wählen sollte.
Re: Webseite print(): Umlaute & Backslashes
Verfasst: Freitag 26. Juli 2019, 12:51
von dd0815
@__blackjack__:
Hier sieht es zumindest so aus, als ob es viele wären:
https://wiki.python.org/moin/WebFrameworks
Habe jetzt ein WSGI-Beispiel gefunden:
https://eddmann.com/posts/understanding ... -examples/
Ich habe herausgefunden, dass ich dieses Programm in der Kommandozeile starten muss, und die Webseite ist dann unter
http://localhost:8080/ tatsächlich erreichbar. Allerdings beim Go-Klicken kommt:
A server error occurred. Please contact the administrator.
Mir fehlt da (natürlicherweise) ganz essenzielles Anfangs-Know-How, was vielleicht für jemand selbstverständlich ist, der jahrelang damit arbeitet, aber irgendwann werdet ihr alle mal diesen Fragen gestellt haben, oder?

Bis jetzt habe ich noch keine Anleitung gefunden, die einen so mitnimmt, dass man eine Chance zum Verstehen hat (immer her mit den Links, so Ihr welche kennt

)
Jedenfalls Euch allen Danke für Eure Hilfe & Zeit...
Viele Grüße,
dd0815
Re: Webseite print(): Umlaute & Backslashes
Verfasst: Freitag 26. Juli 2019, 13:27
von dd0815
Hallo nochmal,
Fehler gefunden, bei der Ausgabe des Names müssen alle Teile in Bytes umgewandelt werden:
Code: Alles auswählen
html = b'Hello, ' + post['name'].value + '!'
html = b'Hello, ' + (post['name'].value).encode('utf-8') + b'!'
Das Laden der Seite per WSGI dauert ca. 4s, meine alte CGI ist sofort da... Hm, aber das Problem hat mein Rechner bei anderen Webseiten auch, das dauert ewig bis diese anfangen zu laden...
Warum suche ich immer in Foren die "als gelöst markieren" Funktion und finde nichts?

Re: Webseite print(): Umlaute & Backslashes
Verfasst: Freitag 26. Juli 2019, 13:31
von __blackjack__
@dd0815: Also ich sehe auf der Wikiseite 8 Rahmenwerke die als „beliebt“ bezeichnet werden. Eigentlich sind es IMHO aber nur die drei von mir genannten. Django und Flask sind jeweils *die* Rahmenwerke wenn es um „komplett“ und „klein“ geht. Bottle nehme ich da gerne noch rein, weil es eben die kleinste, verbreitete Lösung ist, die in einer Datei steckt, die man einfach mit dazu packen kann zum eigenen Code. Das kann in bestimmten Situationen sehr praktisch sein. Alle drei haben gute Dokumentation und werden in der Praxis verwendet – man steht also bei Fragen nicht alleine da.
Das Kodieren als UTF-8 kann man machen, aber das wäre in diesem Fall falsch, denn dann sollte man im ”HTML” auch mitteilen das es UTF-8 kodiert ist. Es wird aber gar kein HTML gesendet. Browser schlucken halt alles…
Edit: Da ist ein Klammerpaar zu viel.
Re: Webseite print(): Umlaute & Backslashes
Verfasst: Freitag 26. Juli 2019, 14:22
von Sirius3
@dd0815: alle der Drei genannten Rahmenwerke haben Tutorials, um den Einstieg so einfach wie möglich zu machen.
Du machst es Dir nur selbst kompliziert, weil Du nicht den Standardweg gehst. Apache und CGI sind Dinosaurier, die einfach nicht aussterben wollen.
Fang frisch an und geh nach Beschreibung eines der Tutorials vor.