komischer Fehler

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
Benutzeravatar
dodo
User
Beiträge: 73
Registriert: Mittwoch 10. November 2010, 13:43

Montag 20. Oktober 2014, 09:26

Hallo,

Ich baue zurzeit ein Templatesystem für mein eigenes Webframework.
Doch es funktioniert nicht wirklich...
Syntax: {%code%} code ist Python Code(z.B. print("Hallo")), {{code}} code ist auch Python code, allerdings wird hier die Rückgabe in den HTML-Code eingebaut. Mit \ kann man {{code}} als "{{code}}" ausgeben lassen(Das '{{' wird ignoriert) und mit \\ kann man einen Backslash ausgeben.

Das Problem ist: Bei "HTML{{python wert}}\\{{kein python code}}\\{%kein python code%}\\\\{%python code%}{%if irgendwas DO%}Irgendein HTML-Code{%END%}ende" kommt

Code: Alles auswählen

print("""HTML"""+python wert+"""{{kein python code}}{{kein python code%}""")
if irgendwas :
 print("""Irgendein HTML-Code""")

print("""ende""")
heraus.

So sieht der Code vom Template-System aus:

Code: Alles auswählen

class SETTemplate(object):
	def __init__(self, template):
		self.newTemplate(template)
	def newTemplate(self, template):
		self.template = "print(\"\"\""
		isPy = False
		isEv = False
		isStr = False
		isEsc = False
		tabs = 0
		index = 0
		while index < len(template):
			i = template[index]
			if isEsc:
				self.template+=i
				index+=1
				isEsc = False
			try:
				if i == "\\":
					isEsc = True
					index+=1
				elif i == "\"" and (isPy or isEv):
					self.template+="\""
					isStr = not isStr
					index+=1
				elif i == "{" and template[index+1] == "%" and not (isPy or isEv):
					self.template+="\"\"\")\n"+(" "*tabs)
					isPy = True
					index+=2
				elif i == "{" and template[index+1] == "{" and not (isPy or isEv):
					self.template+="\"\"\"+"
					isEv = True
					index+=2
				elif i == "%" and template[index+1] == "}" and isPy:
					isPy = False
					self.template+="\n"+(" "*tabs)+"print(\"\"\""
					index+=2
				elif i == "}" and template[index+1] == "}" and isEv:
					isEv = False
					self.template+="+\"\"\""
					index+=2
				elif i == "D" and template[index+1] == "O" and isPy:
					self.template+=":"
					tabs+=1
					index+=2
				elif i == "E" and template[index+1] == "N" and template[index+2] == "D" and isPy:
					tabs-=1
					if tabs<0:
						tabs = 0
					index+=3
				else:
					self.template+=i
					index+=1
			except:
				try:
					self.template+=i
					index+=1
				except:
					break
		self.template+="\"\"\")"
		return self.template
Hilfe wäre nett
Danke im Vorraus,

Dodo
Geht nicht gibts nicht(Das gilt auch für Python)!
BlackJack

Montag 20. Oktober 2014, 09:46

@dodo: Nimm `jinja2`. Oder etwas anderes fertiges.

Ansonsten solltest Du die ”Fehlerbehandlung” überarbeiten. Diese vielen nackten ``except``\s sind keine gute Idee. Ebenso ist das zeichenweise verarbeiten des Templates und erzeugen des Codes keine besonders gute Idee. Das ist hochgradig ineffizient, das zeichenweise verarbeiten weils in Python passiert und das erzeugen des Codes weil Zeichenketten unveränderbar sind, also für fast jedes Zeichen alles bisherige einmal im Speicher herumkopiert werden muss, nur um ein weiteres Zeichen oder eine kurze Zeichenkette anzufügen. Mühsam zu lesen ist dieser Zustandsautomat auch.

Ich würde zuerst einmal das Template mit regulären Ausdrücken in Token zerlegen.
Sirius3
User
Beiträge: 10772
Registriert: Sonntag 21. Oktober 2012, 17:20

Montag 20. Oktober 2014, 09:59

@dodo: zusätzlich zu dem, was BlackJack schon geschrieben hat: Konvention für die Einrücktiefe ist vier Leerzeichen pro Ebene. Ein Blick in den Style Guide for Python Code könnte sich lohnen.
'i' ist ein äußerst schlechter Name für ein Zeichen, da ich (und viele andere) bei 'i' an eine Zahl, insbesondere an einen Laufindex einer Schleife, denken. Python kennt auch das einfache Anführungszeichen als Stringmarkierung. Damit lassen sich die vielen \" vermeiden und die Strings werden deutlich lesbarer. Der Template-Funktionsgenerator sollte statt einer Funktion mit "print" eine mit Stringverarbeitung erzeugen. Solche Funktionen lassen sich viel flexibler einsetzen. Da jeweils nur eines von isPy, isEv, isStr oder isEsc True sein kann, ließe sich diese Variablen zu einer Zustandsvariable zusammenfassen.
Benutzeravatar
snafu
User
Beiträge: 5965
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Montag 20. Oktober 2014, 12:40

@dodo: Neben dem, was die Vorposter geschrieben haben, ist es außerdem unsinnig, eine Klasse zu erstellen, die im Grunde nur aus einer einzigen Methode besteht. Das kann man auch gleich als Funktion schreiben. Klassen werden (unter anderem) dann sinnvoll, wenn du die Arbeit in verschiedene Funktionen gliederst und merkst, dass du gemeinsame Parameter benutzt. Dann kann man diese gemeinsamen Parameter nämlich als Instanzattribute seiner Klasse definieren. Diesen Umstand sehe ich beim bisherigen Zustand deines Programms aber nicht.
Antworten