Re: [Python-de] Maskierung von %
Gerade das wollte ich vermeiden, lese nämlich einen kompletten SQL ein und wollte diesen mit nur einer/mehreren Zeilen erweitern. Da im Text häufiger ein "wert like '%suchbegriff%'" steht, müsste ich immer dieses Sonderzeichen eintragen, das ist mühsam und unleserlich :( Bis dann, Volker -------- Original-Nachricht -------- Datum: Fri, 02 Feb 2007 13:45:42 +0100 Von: Christian Klinger <cklinger@novareto.de> An: Volker Helm <Helm.volker@gmx.de> CC: Betreff: Re: [Python-de] Maskierung von %
Volker Helm schrieb:
Hi,
wollte gerade einen String zur Ausgabe erstellen:
s = "prozentuale Spanne %.2f %" % 15.23
Ergebnis sollte seind:
prozentuale Spanne 15.23 %
Leider wirft das System einen "ValueError: incomplete format" aus.
Gibt es eine Möglichkeit das %-Zeichen zu maskieren, dass es nicht nach einer weiteren Variablen sucht? "\%" funktioniert leider nicht.
Bis dann,
Volker
Hallo
vielleicht so:
Python 2.3.5 (#1, Aug 22 2005, 22:13:23) [GCC 3.3 20030304 (Apple Computer, Inc. build 1809)] on darwin Type "help", "copyright", "credits" or "license" for more information.
a="%.2f %s" %(12.2,'%') a '12.20 %'
mfg Chrisitan
-- "Feel free" - 10 GB Mailbox, 100 FreeSMS/Monat ... Jetzt GMX TopMail testen: http://www.gmx.net/de/go/topmail?ac=OM.GX.GX003K11713T4783a
Volker Helm schrieb:
Gerade das wollte ich vermeiden, lese nämlich einen kompletten SQL ein und wollte diesen mit nur einer/mehreren Zeilen erweitern.
Was heißt erweitern? Anhängen oder irgendwo zwischen drin einfügen? Wenn ersteres: x = 15.23 s = sqlstring + "prozentuale Spanne %.2f %%" % x Wenn letzteres, dann musst du es ja wohl entweder manuell machen, oder du hast dafür auch einen Algorithmus (z.B. regular expressions), dann machst du die string substitution halt bevor du die Zeilen einfügst: import re sqlstring = u"Irgendein Text der Prozentzeichen (%) enthält. ${PLATZHALTER}. Noch mehr Text" sqlstring = re.sub(r'\$\{PLATZHALTER\}', "prozentuale Spanne %.2f %%" % x, sqlstring)
Da im Text häufiger ein "wert like '%suchbegriff%'" steht, müsste ich immer dieses Sonderzeichen eintragen, das ist mühsam und unleserlich :(
Da kann dir Python helfen: s = s.replace('%', '%%') natürlich, bevor du Platzhalter wie %s usw. einfügst. Chris
Hi Volker, On 2007-02-02 14:09, Volker Helm wrote:
Da im Text häufiger ein "wert like '%suchbegriff%'" steht, müsste ich immer dieses Sonderzeichen eintragen, das ist mühsam und unleserlich :(
dazu noch ein Hinweis: Setze den Suchbegriff als Argument in cursor.execute ein. Dadurch werden Zeichen, die in SQL Sonderzeichen sind (vor allem ' , bei manchen SQL-Dialekten auch \), richtig maskiert. Also nicht suchtext = "Python's Prozentzeichen" cursor.execute( "SELECT text FROM table WHERE text LIKE '%%%s%%'" % suchtext) # selbst eingesetzt - unsicher sondern suchtext = "Python's Prozentzeichen" cursor.execute( "SELECT text FROM table WHERE text LIKE '%%(suchtext)s%'", {'suchtext': suchtext}) # vom DB-Adapter eingesetzt - besser Beachte, dass hier der execute-Methode zwei Argumente übergeben werden. Außerdem musst du die Prozentzeichen am Anfang und Ende des Strings nicht verdoppeln (wenn der Datenbankadapter sauber programmiert ist). Wie einzusetzende Zeichenketten zu formatieren sind und wie das zweite Argument von cursor.execute aussehen muss, hängt vom konkreten Datenbankadapter ab. Näheres in der DB-API 2.0, an die sich alle neueren Adapter halten sollten, http://www.python.org/dev/peps/pep-0249/ , und der Doku zum von dir verwendeten Datenbankadapter. Viele Grüße Stefan
Stefan Schwarzer schrieb:
Hi Volker,
On 2007-02-02 14:09, Volker Helm wrote:
Da im Text häufiger ein "wert like '%suchbegriff%'" steht, müsste ich immer dieses Sonderzeichen eintragen, das ist mühsam und unleserlich :(
dazu noch ein Hinweis: Setze den Suchbegriff als Argument in cursor.execute ein. Dadurch werden Zeichen, die in SQL Sonderzeichen sind (vor allem ' , bei manchen SQL-Dialekten auch \), richtig maskiert.
Also nicht
suchtext = "Python's Prozentzeichen" cursor.execute( "SELECT text FROM table WHERE text LIKE '%%%s%%'" % suchtext) # selbst eingesetzt - unsicher
sondern
suchtext = "Python's Prozentzeichen" cursor.execute( "SELECT text FROM table WHERE text LIKE '%%(suchtext)s%'", {'suchtext': suchtext}) # vom DB-Adapter eingesetzt - besser
Beachte, dass hier der execute-Methode zwei Argumente übergeben werden. Außerdem musst du die Prozentzeichen am Anfang und Ende des Strings nicht verdoppeln (wenn der Datenbankadapter sauber programmiert ist). Wie einzusetzende Zeichenketten zu formatieren sind und wie das zweite Argument von cursor.execute aussehen muss, hängt vom konkreten Datenbankadapter ab. Näheres in der DB-API 2.0, an die sich alle neueren Adapter halten sollten, http://www.python.org/dev/peps/pep-0249/ , und der Doku zum von dir verwendeten Datenbankadapter.
Viele Grüße Stefan
hm.. dass verstehe ich ehrlich gesagt nicht. ich will doch nicht das ganze query escapen, sondern nur bestimmte einzelne eingaben von usern. mfg Light Lan
Hallo Paul, On 2007-02-02 18:48, Paul Rauch wrote:
Stefan Schwarzer schrieb:
dazu noch ein Hinweis: Setze den Suchbegriff als Argument in cursor.execute ein. Dadurch werden Zeichen, die in SQL Sonderzeichen sind (vor allem ' , bei manchen SQL-Dialekten auch \), richtig maskiert.
Also nicht
suchtext = "Python's Prozentzeichen" cursor.execute( "SELECT text FROM table WHERE text LIKE '%%%s%%'" % suchtext) # selbst eingesetzt - unsicher
sondern
suchtext = "Python's Prozentzeichen" cursor.execute( "SELECT text FROM table WHERE text LIKE '%%(suchtext)s%'", {'suchtext': suchtext}) # vom DB-Adapter eingesetzt - besser
Beachte, dass hier der execute-Methode zwei Argumente übergeben werden. Außerdem musst du die Prozentzeichen am Anfang und Ende des Strings nicht verdoppeln (wenn der Datenbankadapter sauber programmiert ist). Wie einzusetzende Zeichenketten zu formatieren sind und wie das zweite Argument von cursor.execute aussehen muss, hängt vom konkreten Datenbankadapter ab. Näheres in der DB-API 2.0, an die sich alle neueren Adapter halten sollten, http://www.python.org/dev/peps/pep-0249/ , und der Doku zum von dir verwendeten Datenbankadapter.
dass verstehe ich ehrlich gesagt nicht. ich will doch nicht das ganze query escapen, sondern nur bestimmte einzelne eingaben von usern.
bei der Variante mit dem zweiten Parameter werden alle Query- Parameter angegeben, die das SQL-Statement enthält. Dazu gehören "normale" Daten wie Zeichenketten, Zahlen und Datums- werte, nicht jedoch z. B. ein Tabellenname hinter FROM. Andererseits holt man die sich ja normalerweise nicht von einem Benutzer der Webschnittstelle. :-) Für dein Beispiel aus dem anderen Unter-Thread sähe die SQL- Ausführung so aus (ungetestet): # von irgendwoher, bspw. Webschnittstelle x = "Nutzereingabe" # ggf. mit Sonderzeichen y = "Bla" # ggf. mit Sonderzeichen cursor.execute( # nach dem SQL-Query steht ein Komma, kein %, d. h. # der Datenbankadapter übernimmt das Einsetzen der # Parameter - richtig maskiert "UPDATE db.table SET x='%(neu)s' WHERE y='%(kriterium)s' LIMIT 1", {'neu': x, 'kriterium': y}) Eine Bemerkung am Rande: Wenn du den LIMIT-Zusatz wirklich brauchst, hast du eine recht ungewöhnliche Anwendung. ;-) Viele Grüße Stefan
Stefan Schwarzer schrieb:
Hallo Paul,
On 2007-02-02 18:48, Paul Rauch wrote:
Stefan Schwarzer schrieb:
dazu noch ein Hinweis: Setze den Suchbegriff als Argument in cursor.execute ein. Dadurch werden Zeichen, die in SQL Sonderzeichen sind (vor allem ' , bei manchen SQL-Dialekten auch \), richtig maskiert.
Also nicht
suchtext = "Python's Prozentzeichen" cursor.execute( "SELECT text FROM table WHERE text LIKE '%%%s%%'" % suchtext) # selbst eingesetzt - unsicher
sondern
suchtext = "Python's Prozentzeichen" cursor.execute( "SELECT text FROM table WHERE text LIKE '%%(suchtext)s%'", {'suchtext': suchtext}) # vom DB-Adapter eingesetzt - besser
Beachte, dass hier der execute-Methode zwei Argumente übergeben werden. Außerdem musst du die Prozentzeichen am Anfang und Ende des Strings nicht verdoppeln (wenn der Datenbankadapter sauber programmiert ist). Wie einzusetzende Zeichenketten zu formatieren sind und wie das zweite Argument von cursor.execute aussehen muss, hängt vom konkreten Datenbankadapter ab. Näheres in der DB-API 2.0, an die sich alle neueren Adapter halten sollten, http://www.python.org/dev/peps/pep-0249/ , und der Doku zum von dir verwendeten Datenbankadapter.
dass verstehe ich ehrlich gesagt nicht. ich will doch nicht das ganze query escapen, sondern nur bestimmte einzelne eingaben von usern.
bei der Variante mit dem zweiten Parameter werden alle Query- Parameter angegeben, die das SQL-Statement enthält. Dazu gehören "normale" Daten wie Zeichenketten, Zahlen und Datums- werte, nicht jedoch z. B. ein Tabellenname hinter FROM. Andererseits holt man die sich ja normalerweise nicht von einem Benutzer der Webschnittstelle. :-)
Für dein Beispiel aus dem anderen Unter-Thread sähe die SQL- Ausführung so aus (ungetestet):
# von irgendwoher, bspw. Webschnittstelle x = "Nutzereingabe" # ggf. mit Sonderzeichen y = "Bla" # ggf. mit Sonderzeichen
cursor.execute( # nach dem SQL-Query steht ein Komma, kein %, d. h. # der Datenbankadapter übernimmt das Einsetzen der # Parameter - richtig maskiert "UPDATE db.table SET x='%(neu)s' WHERE y='%(kriterium)s' LIMIT 1", {'neu': x, 'kriterium': y})
Eine Bemerkung am Rande: Wenn du den LIMIT-Zusatz wirklich brauchst, hast du eine recht ungewöhnliche Anwendung. ;-)
Viele Grüße Stefan
den LIMIT zusatz mache ich nur aus Gewohnheit, kommt nicht gut, wenn ein update ohne WHERE und LIMIT durchrutscht... und danke, jetzt hab ichs verstanden :)
email = 'LightLan@lightlan.de' name = 'Vorname\'\' \n Nachname' cursor.execute('INSERT INTO test.entry(name,email) VALUES(%(name)s,%(email)s)',{'name':name,'email':email})
geht einwandfrei :) mfg Light Lan
Hi Stefan, gute Idee, allerdings ist es bei mir wohl kein Problem der Sicherheit. Erstens wird das Script nur intern verwendet, zweitens wird der SQL fest definiert, nur um die entsprechenden Einschränkungen erweitert, so kann ich eine Funktion für 5 SQL-Abfragen einsetzen (Blöde Adresssuche nach Namen, Telefon etc.). Die zusätzlichen individuellen Parameter werden über feste Bindungen übergeben: cur.execute("""select name,nummer from table where name like '%'||:p_begriff||'%'""", p_begriff = Suchbegriff) Danke aber trotzdem, Volker -------- Original-Nachricht -------- Datum: Fri, 02 Feb 2007 15:02:39 +0100 Von: Stefan Schwarzer <sschwarzer@sschwarzer.net> An: python-de@python.net CC: Betreff: Re: [Python-de] Maskierung von %
Hi Volker,
On 2007-02-02 14:09, Volker Helm wrote:
Da im Text häufiger ein "wert like '%suchbegriff%'" steht, müsste ich immer dieses Sonderzeichen eintragen, das ist mühsam und unleserlich :(
dazu noch ein Hinweis: Setze den Suchbegriff als Argument in cursor.execute ein. Dadurch werden Zeichen, die in SQL Sonderzeichen sind (vor allem ' , bei manchen SQL-Dialekten auch \), richtig maskiert.
Also nicht
suchtext = "Python's Prozentzeichen" cursor.execute( "SELECT text FROM table WHERE text LIKE '%%%s%%'" % suchtext) # selbst eingesetzt - unsicher
sondern
suchtext = "Python's Prozentzeichen" cursor.execute( "SELECT text FROM table WHERE text LIKE '%%(suchtext)s%'", {'suchtext': suchtext}) # vom DB-Adapter eingesetzt - besser
Beachte, dass hier der execute-Methode zwei Argumente übergeben werden. Außerdem musst du die Prozentzeichen am Anfang und Ende des Strings nicht verdoppeln (wenn der Datenbankadapter sauber programmiert ist). Wie einzusetzende Zeichenketten zu formatieren sind und wie das zweite Argument von cursor.execute aussehen muss, hängt vom konkreten Datenbankadapter ab. Näheres in der DB-API 2.0, an die sich alle neueren Adapter halten sollten, http://www.python.org/dev/peps/pep-0249/ , und der Doku zum von dir verwendeten Datenbankadapter.
Viele Grüße Stefan
_______________________________________________ python-de maillist - python-de@python.net http://python.net/mailman/listinfo/python-de
-- "Feel free" - 5 GB Mailbox, 50 FreeSMS/Monat ... Jetzt GMX ProMail testen: http://www.gmx.net/de/go/promail?ac=OM.GX.GX003K11711T4781a
Hi Volker, On 2007-02-05 09:21, Volker Helm wrote:
gute Idee, allerdings ist es bei mir wohl kein Problem der Sicherheit. Erstens wird das Script nur intern verwendet,
auch, wenn der Hinweis auf den zusätzlichen Parameter meist im Zusammenhang mit der Sicherheit kommt, ist er auch in allen anderen Fällen sinnvoll. Wenn eine einzusetzende Zeichenkette ein Apostroph ' enthält, gibt es dann zwar wahrscheinlich keine ausgenutzte Sicherheitslücke - aber einen Fehler bei der SQL-Ausführung. Daher sollte man _immer_ mit dem zweiten (und ggf. weiteren) Argument(en) von cursor.execute arbeiten, das macht den Code generell robuster.
zweitens wird der SQL fest definiert, nur um die entsprechenden Einschränkungen erweitert, so kann ich eine Funktion für 5 SQL-Abfragen einsetzen (Blöde Adresssuche nach Namen, Telefon etc.). Die zusätzlichen individuellen Parameter werden über feste Bindungen übergeben: cur.execute("""select name,nummer from table where name like '%'||:p_begriff||'%'""", p_begriff = Suchbegriff)
Was du hier ja auch tust. :-) Viele Grüße Stefan
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 Hallo Stefan,
suchtext = "Python's Prozentzeichen" cursor.execute( "SELECT text FROM table WHERE text LIKE '%%(suchtext)s%'", {'suchtext': suchtext}) # vom DB-Adapter eingesetzt - besser
Sicher, dass Du das so willst? Denn falls der 'suchtext' ein Leer-/Sonderzeichen enthält, wird er escaped. Dann bekommst Du diese query: ... LIKE '%'such mich'%' ... Das ist sicher nicht das gewünschte :-) Besser _alles_ Quoting dem Treiber überlassen, das kann das im Zweifelsfall besser. Also: suchtext = "Python's Prozentzeichen" cursor.execute( "SELECT text FROM table WHERE text LIKE %(suchtext)s", {'suchtext': '%' + suchtext + '%' }) - -- Schönen Gruß - Regards Hartmut Goebel | Hartmut Goebel | IT-Security -- effizient | | h.goebel@goebel-consult.de | www.goebel-consult.de | -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.5 (GNU/Linux) Comment: Using GnuPG with Mandriva - http://enigmail.mozdev.org iQEVAwUBRccwkczajR0mSa83AQKTOQgAgBzEaIMsSufn8b1CJoMk80LLZestubcj z42+WYgpCKFclN9+NFkVAcksoWPXdBX4JwX/LXiM0uCHYU009lCKOPbtOLJqVrTC k/iMoXuWvSWk31W0IysHdhgg0jBnBWogsqh0RzcMexzMCMBsMzx6z4H6c5gYweI6 0VdF89ia5gHHPqca3DErUrrMOcV5Uzcs9vpq3S0RN1fHCN0gcDwQo4qgRgdMCgMQ aLNOlm0GL2I1mSALJj1skWVAr8wkNC4LaGY/z+gL86kA1LNVyQu1NOElFm00yT+Q blRKI4bHCzfVFRVDrrRIP/nml/zSO12uLl+DRdH2Rgj/7Le0we4AMQ== =5w97 -----END PGP SIGNATURE-----
Ich sollte vielleicht mal klarstellen, dass mein Problem gelöst ist. Es war folgendes, in einem SQL wird bei mir abgehandelt, ob es einen Rabatt gibt und um welche Art es sich handelt ('€', '%', 'Mengenrabatt'). Leider wird dieser SQL im Anschluß erweitert, abhängig, ob es sich um eine Position eines Auftrages handelt, oder um alle. Dies wird mittels: sql = """select blub, rabatt, case when rabatttyp = 0 then '%' else '€' end rabattyp from table where auftrag = :auftrag %s""" sqlauftrag = "" sqlposition = "and position = :position" erweitert. Durch das vorhanden sein des Prozentzeichens klappt der gesamte Vorgang nicht, habe die Maskierung in der Dokumentation leider überlesen. Sollten Begriffe mit like gesucht werden, werden die entsprechenden Werte entweder vom Benutzer als '%Hans%Müller%' eingegeben werden müssen oder werden entschprechend vorne und hinten um ein '%' Zeichen erweitert. suchbegriff = '%'+Eingabe.strip('%')+'%' Der Suchbegriff wird dann mittels eines Dictionary variablen = {'Suchbegriff': suchbegriff} und der Anweisung cur.execute(sql,variablen) verbunden und abgeschickt. So, noch einen schönen Tag, Volker
Hallo Stefan,
suchtext = "Python's Prozentzeichen" cursor.execute( "SELECT text FROM table WHERE text LIKE '%%(suchtext)s%'", {'suchtext': suchtext}) # vom DB-Adapter eingesetzt - besser
Sicher, dass Du das so willst? Denn falls der 'suchtext' ein Leer-/Sonderzeichen enthält, wird er escaped. Dann bekommst Du diese query:
... LIKE '%'such mich'%' ...
Das ist sicher nicht das gewünschte :-)
Besser _alles_ Quoting dem Treiber überlassen, das kann das im Zweifelsfall besser. Also:
suchtext = "Python's Prozentzeichen" cursor.execute( "SELECT text FROM table WHERE text LIKE %(suchtext)s", {'suchtext': '%' + suchtext + '%' })
- -- Schönen Gruß - Regards Hartmut Goebel
| Hartmut Goebel | IT-Security -- effizient | | h.goebel@goebel-consult.de | www.goebel-consult.de | -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.5 (GNU/Linux) Comment: Using GnuPG with Mandriva - http://enigmail.mozdev.org
iQEVAwUBRccwkczajR0mSa83AQKTOQgAgBzEaIMsSufn8b1CJoMk80LLZestubcj z42+WYgpCKFclN9+NFkVAcksoWPXdBX4JwX/LXiM0uCHYU009lCKOPbtOLJqVrTC k/iMoXuWvSWk31W0IysHdhgg0jBnBWogsqh0RzcMexzMCMBsMzx6z4H6c5gYweI6 0VdF89ia5gHHPqca3DErUrrMOcV5Uzcs9vpq3S0RN1fHCN0gcDwQo4qgRgdMCgMQ aLNOlm0GL2I1mSALJj1skWVAr8wkNC4LaGY/z+gL86kA1LNVyQu1NOElFm00yT+Q blRKI4bHCzfVFRVDrrRIP/nml/zSO12uLl+DRdH2Rgj/7Le0we4AMQ== =5w97 -----END PGP SIGNATURE-----
_______________________________________________ python-de maillist - python-de@python.net http://python.net/mailman/listinfo/python-de
-- "Feel free" - 5 GB Mailbox, 50 FreeSMS/Monat ... Jetzt GMX ProMail testen: http://www.gmx.net/de/go/promail?ac=OM.GX.GX003K11711T4781a
participants (5)
-
Christopher Arndt
-
Hartmut Goebel
-
Paul Rauch
-
Stefan Schwarzer
-
Volker Helm