Wie kann ich am schnellsten einen Docstring nach einem Ausdruck der Form "<<XXX>>" durchsuchen, wobei XXX ein unbekannter String ist (welche natürlich nicht ">>" enthält) und nicht bekannt ist, ob der Docstring meinen Ausdruck überhaupt enthält?
Ist es in dem Fall schneller mit re's oder mit string-eigenen Funktionen?
Das "<<" und ">>"-Geraffel kann ich auch beliebig ändern, ich will nur einen bestimmten String innerhalb meines Docstrings markieren, so dass ich ihn mit möglichst wenig Laufzeitaufwand wieder rausfischen kann.
Halbwegs einfachen Ausdruck finden möglichst ohne re?
- jens
- Python-Forum Veteran
- Beiträge: 8502
- Registriert: Dienstag 10. August 2004, 09:40
- Wohnort: duisburg
- Kontaktdaten:
In PyLucid gibt es den sourcecode_parser.py:
Wenn du die __call__ Methode umschreibst, kannst du dammit nur DocStrings rausfiltern. Im Weiteren Schritt, kannst du dann nach deinen Markierungen Suche...
Code: Alles auswählen
#!/usr/bin/python
# -*- coding: UTF-8 -*-
"""
Source Code Parser
Based on J�en Hermann's "MoinMoin - Python Source Parser"
http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/52298/
"""
__version__="0.2.0"
__history__="""
v0.2.0
- Einige Optimierungen
- Bug mit den speziellen Zeilenumbrüche mit \ am ende (kein Zeilenumbruch) behoben
v0.1.0
- aus SourceCode.py Plugin entnommen, damit er auch f�tinyTextile genutzt werden kann
"""
import sys, cgi, cStringIO, \
keyword, token, tokenize
token.KEYWORD = token.NT_OFFSET + 1
class python_source_parser:
def parse( self, raw_txt ):
"""
Parse and send the colored source.
"""
self.special_not_newline = False
self.raw = raw_txt.expandtabs()
# store line offsets in self.lines
self.lines = [0, 0]
pos = 0
while 1:
pos = self.raw.find( '\n', pos ) + 1
if not pos: break
self.lines.append( pos )
self.lines.append( len(self.raw) )
# parse the source and write it
self.pos = 0
text = cStringIO.StringIO( self.raw )
try:
tokenize.tokenize(text.readline, self)
except tokenize.TokenError, ex:
msg = ex[0]
line = ex[1][0]
print "<h3>ERROR: %s</h3>%s\n" % (
msg, self.raw[self.lines[line]:]
)
print "<br />\n"
def __call__(self, toktype, toktext, (srow,scol), (erow,ecol), line):
""" Token handler.
"""
# calculate new positions
oldpos = self.pos
newpos = self.lines[srow] + scol
self.pos = newpos + len(toktext)
# Patch for special not newline with \
if line.endswith("\\\n") and toktype!=tokenize.COMMENT:
self.special_not_newline = True
elif self.special_not_newline == True:
self.special_not_newline = False
print "\\<br />\n"
# handle newlines
if toktype in (token.NEWLINE, tokenize.NL):
sys.stdout.write( '<br />\n' )
return
# Spaces
if newpos > oldpos:
sys.stdout.write(" " * (newpos-oldpos))
if toktext=="":
return
# map token type to a color group
if token.LPAR <= toktype and toktype <= token.OP:
toktype = token.OP
elif toktype == token.NAME and keyword.iskeyword(toktext):
toktype = token.KEYWORD
# Text Escapen
toktext = cgi.escape( toktext )
# Non-Breaking-Spaces
toktext = toktext.replace(" "," ")
# Zeilenumbrüche umwandeln
toktext = toktext.replace("\n","<br />\n")
if toktype==token.NAME:
sys.stdout.write(toktext)
else:
sys.stdout.write('<span class="t%s">%s</span>' % (toktype,toktext))
#~ print "\n>>>",toktype
if __name__ == '__main__':
python_source_parser().parse(open(__file__).read())
-
- Python-Forum Veteran
- Beiträge: 1209
- Registriert: Montag 29. September 2003, 17:18
- Wohnort: Purkersdorf (bei Wien [Austria])
Hi!
Also das Muster rausfiltern würde ich schon mit einer Regex machen. Mit den string-Funktionen fällt mir auf die Schnelle keine Lösung ein, die einfach und schnell sein sollte. Und re's sind ja auch nicht so langsam Schneller programmiert ist auf jedenfall die Version mit re
Gruß, mawe
Also das Muster rausfiltern würde ich schon mit einer Regex machen. Mit den string-Funktionen fällt mir auf die Schnelle keine Lösung ein, die einfach und schnell sein sollte. Und re's sind ja auch nicht so langsam Schneller programmiert ist auf jedenfall die Version mit re
Gruß, mawe
Vielleicht so in etwa:
Code: Alles auswählen
a = "ababa<<teststring1>>cbcbc<<teststring2>>dcdc"
lastfoundindex = 0
s1 = '<<'
s2 = '>>'
found = []
while 1:
lf1 = a.find(s1, lastfoundindex) + len(s1)
lf2 = a.find(s2, lastfoundindex)
if lf1 > -1 and lf2 > -1 and lf1 < lf2:
found.append (a[lf1:lf2])
lastfoundindex = lf2 + 1
else:
break
print "Strings found:"
for s in found:
print s
Vielleicht hätte ich dazu sagen sollen, dass der Ausdruck höchstens einmal vorkommen soll, da die docstrings nicht von den endnutzern manipuliert werden kann ich schon davon ausgehen, dass das auch eingehalten wird.
Von daher hätte ich jetzt überlegt, evtl. mit str.find ranzugehen und den linken und rechten delimiter einzeln zu suchen.
Wobei mir gerade in meinem Bsp auffällt, dass ">>" eine ungünstige Wahl ist, wenn z.B. doctest im Spiel ist...
Von daher hätte ich jetzt überlegt, evtl. mit str.find ranzugehen und den linken und rechten delimiter einzeln zu suchen.
Wobei mir gerade in meinem Bsp auffällt, dass ">>" eine ungünstige Wahl ist, wenn z.B. doctest im Spiel ist...