Nachvollzug von PythonCode: traceReport -> Version 0.2

Stellt hier eure Projekte vor.
Internetseiten, Skripte, und alles andere bzgl. Python.
Antworten
bastian.weber
User
Beiträge: 15
Registriert: Montag 4. August 2008, 23:30
Wohnort: Dresden

Donnerstag 7. August 2008, 14:27

Ausgangspunkt war meine Suche nach einem solchen Tool, siehe auch:
http://www.python-forum.de/topic-15616. ... 2c19288925

Dank des Hinweises auf sys.settrace() habe ich mich dann selbst mal dran gemacht.
Das Modul ist in einem Zustand, in dem es für mich seinen Zweck erstmal erfüllt.
Ich kann mir aber gut vorstellen, dass es (mit einigen Anpassungen) auch für andere Entwickler hilfreich ist.

Feedback (positiv und negativ) ist erwünscht!

Hier die erforderliche css-Datei format.css (stark angelehnt, an die dieses Forums):
http://paste.pocoo.org/show/81495/

und hier ist das Modul :
http://paste.pocoo.org/show/81496/




Und hier eine schnell zusammengeschusterte Beispielnutzung die außer ein paar Funktionsaufrufen nichts macht:

Code: Alles auswählen

#!/usr/bin/python
# -*- coding: utf8 -*-
import sys
import traceReport     

class A:
    def fcn2(self, e, f):
        k=e-f
        s=k.__str__()
        s=s.strip()
        return s
    
    def fcn3(self):
        return 0
        

class B(object):
    p="eins zwei drei"

def fcn1(a,b):
    c=a+b
    if a>b:
        c+=1
    else:
        c=None
    d=fcn2(4)
    myA=A()
    myA.fcn3()
    myA.fcn2(4,3)
    l=B.p.split()
    k=l[1]
    return c

def fcn2(end):
    """docstring"""
    for i in range(10):
        if i>= end:
            break
    k="""multi
    line
    teststring
    """  
    return 100


print "Start Tracing"
traceReport.starttrace()
fcn1(5,1)
traceReport.stoptrace()
print "End of Tracing ... see report.html"

traceReport.genHTMLReport("report.html")


und so sieht das Ergebnis aus:
Bild
...

Wie gesagt, ich bitte um Feedback jedweder Art.

Gruß,
Bastian.

Edit: Im Titel auf neue Version hingewiesen
Zuletzt geändert von bastian.weber am Freitag 22. August 2008, 20:30, insgesamt 3-mal geändert.
Benutzeravatar
erebus
User
Beiträge: 3
Registriert: Freitag 8. August 2008, 10:52

Freitag 8. August 2008, 12:05

Du solltest erwähnen, dass man das Modul IPython installiert haben muss. Und die Schrift ist ein wenig klein (1280x1024, Firefox, normale Schriftgrößenvoreinstellung, siehe Bild). Ansonsten schon sehr fein.

Bild

LG erebus
bastian.weber
User
Beiträge: 15
Registriert: Montag 4. August 2008, 23:30
Wohnort: Dresden

Samstag 9. August 2008, 18:39

Das mit IPython stimmt.

Allerdings hatte ich das nur zum Entwickeln drin. Für die eigentliche Funktion des Moduls ist IPython nicht notwendig. Die entsprechenden Zeilen können deshalb problemlos aus dem Code entfernt werden.

Ich hab es aber drin gelassen, weil ich selber auch froh war, als ich die Variante mit der eingebetteten IPython shell entdeckt hatte, und dachte dass es andere vielleicht auch nützlich finden würden.

Die Schriftgröße ist Geschmackssache. Ich wollte halt möglichst ne platzsparend Anzeige, und hab deshalb eine Größe in der Nähe der unteren Schmerzgrenze gewählt. das kann man ja aber über die css-Datei einfach anpassen.

Gruß, Bastian.
Y0Gi
User
Beiträge: 1454
Registriert: Freitag 22. September 2006, 23:05
Wohnort: ja

Mittwoch 13. August 2008, 12:45

Sehr schön, scheint mir auf den ersten Blick genau das zu sein, was ich suche. Aus Perl kenne ich sowas, aus Python bisher noch nicht.

Was die Schriftgröße angeht: In Firefox werden bei mir Monospace-Codeschnipsel sehr klein angezeigt. IIRC habe ich mal gelesen, dass es an dem insgesamt kleineren Schriftbild bestimmter Schriftarten (Courier New vs. Courier?) liegt und dass ich die mal explizit benannt habe, was das Problem behob. Vielleicht hilft's.
Benutzeravatar
veers
User
Beiträge: 1219
Registriert: Mittwoch 28. Februar 2007, 20:01
Wohnort: Zürich (CH)
Kontaktdaten:

Mittwoch 13. August 2008, 18:29

Nett!

Etwas Feedback:

Schau dir mal das Style Guide (PEP-8) an.

Bau das:

Code: Alles auswählen

from IPython.Shell import IPShellEmbed
args = ['-pi1','In <\\#>: ','-pi2','   .\\D.: ',
            '-po','Out<\\#>: ','-nosep']        
IPS= IPShellEmbed(args,
                       banner = 'Dropping into IPython',
                       exit_msg = 'Leaving Interpreter, back to program.')
...
if __name__ == "__main__":
    pass
Doch so um:

Code: Alles auswählen

def main():
    # ipython code evtl mit fallback zu normalem interaktivem interpreter

if __name__ == "__main__":
    main()

Code: Alles auswählen

                line=""
                line+="<tr>"
                line+="<td class='codebb_linenumbers'>%s:%03d</td>" %(fileName, int(fileLine))
                line+="<td class='codebb_code'>%s</td>" %(formatedLines[i])
                line+="<td class='codebb_info'>%s</td>" % cgi.escape(infoString)
                line+="</tr>\n"
Warum nicht table.append("<tr>") ...?

Das TRC global ist stört mich auch etwas ;)

Das ganze so bauen das kein Sourcecode editieren mehr notwendig ist und dann ab damit in den pypi ;)
[url=http://29a.ch/]My Website - 29a.ch[/url]
"If privacy is outlawed, only outlaws will have privacy." - Phil Zimmermann
bastian.weber
User
Beiträge: 15
Registriert: Montag 4. August 2008, 23:30
Wohnort: Dresden

Donnerstag 14. August 2008, 00:57

Hi veers.

Danke für das Feedback.

Wahrscheinlich nehme ich die eingebettete IPython Shell raus, weil es, wie gesagt, nicht zur eigentlichen Funktionalität beiträgt sondern nur zum debuggen nützlich ist.

PEP-8 sollte ich mir vielleicht wirklich mal durchlesen.


TRC auf Modulebene global zu machen hat mir auch nicht besonders gefallen. Auf der anderen Seite finde ich es zu aufwendig eine solches Objekt immer von einer Methode zur anderen durchzureichen.

Das Problem habe ich öfter. Gibt es dafür irgendein schlaues Entwurfsmuster?
Warum nicht table.append("<tr>") ...?
stimmt eigentlich.

Wahrscheinlich wird es aber noch ein bisschen anders. Nachdem ich inzwischen ein paar Features hinzugefügt habe, z.Bsp. Faltbare HTML-Ausgabe, Infos über Änderungen von Variablen nach dem ausführen einer Codezeile, und noch ein paar kleine Sachen, bin ich jetzt an einem Punkt an dem selbst ich merke, dass es Zeit für ein Refactoring bzw. eine neuStrukturierung ist. Irgendwie muss ich Inhalt und Form stärker Trennen. Am liebsten wäre es mir im pythonCode keine HTML Tags zu haben, und auch kein JavaScript, wie es inzwischen bei der aktuellen Version der Fall ist. Irgendwie riecht das nach Templates, aber Ahnung, wie man so was benutzt, und ob sich der Aufwand lohnt hab ich leider keine.

Das mit pypi schmeichelt mir ;) Kann da eigentlich jeder was hochladen?
Vorher gibts aber hier nochmal was zum testen. Evtl nächste Woche.
Y0Gi
User
Beiträge: 1454
Registriert: Freitag 22. September 2006, 23:05
Wohnort: ja

Donnerstag 14. August 2008, 11:40

Strinkonkatenation ist echt böse, da dann jedes mal ein neuer, atomarer String erzeugt wird. Daher verwendet man Listen. Anstelle von `list.append()` würde ich da `yield` benutzen. Wenn du jedoch (zu Recht) sowieso kein Markup im Code sehen willst, dann verwende doch eine Template-Engine. Da gibt es zum einen (ich nenne mal die aktuell beliebtesten) XML-basierte (Genshi) und textbasierte (Jinja, Mako, Cheetah).
bastian.weber
User
Beiträge: 15
Registriert: Montag 4. August 2008, 23:30
Wohnort: Dresden

Donnerstag 21. August 2008, 23:08

Eine neue Version ist fertig:

(Weil es fürs copy-pasten mittlerweile zu viele Dateien sind, hab ich den erstbesten File-Hoster gewählt, den ich finden konnte.)
http://www.2shared.com/file/3801800/40f ... ha-02.html

Sie sollte stabiler sein, als die vorherige und bessere Ausgaben produzieren.
(stabile Tabellenbreite, faltbare Funktionsaufrufe, Verarbeitung von logischen Zeielen, die aus mehreren physischen bestehen, Ausgabe von Änderungen von Variablen in einer Zeile, ...)
Ein bisschen Geduld ist vielleicht angebracht, die Ausführungsgeschwindigkeit des ge-trace-ten Codestücks sinkt nämlich deutlich gegenüber der normalen Ausführung. Aber schneller als manuell print -Anweisungen in den Code einzubauen, ist es allema.

Bevor ich es, wenn überhaupt, in den pypi stelle, würde ich gerne noch ein paar Stimmen hören.
Es pep8-konform zu machen hab ich auf jeden Fall noch vor.... :wink:
Y0Gi
User
Beiträge: 1454
Registriert: Freitag 22. September 2006, 23:05
Wohnort: ja

Sonntag 24. August 2008, 23:26

Taugt es für Tests? Ist es möglich auszugeben, wie oft eine Zeile im Code ausgeführt wurde? So für Coverage-Auswertung?
audax
User
Beiträge: 830
Registriert: Mittwoch 19. Dezember 2007, 10:38

Montag 25. August 2008, 00:03

Es kommt mit Cython-Modulen nicht zurecht :]

Code: Alles auswählen

>>> genReport("blub.html")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "traceReport/traceReport.py", line 153, in genReport
    genHTMLReport(filename, r)
  File "/home/dax/compile/traceReport/traceReport/markup.py", line 333, in genHTMLReport
    myFile.write(tg.genTab(eventList))
  File "/home/dax/compile/traceReport/traceReport/markup.py", line 129, in genTab
    table.append(self.__genCallLines(event))
  File "/home/dax/compile/traceReport/traceReport/markup.py", line 200, in __genCallLines
    retval=self.addBreaks(event.retVal)
  File "/home/dax/compile/traceReport/traceReport/markup.py", line 262, in addBreaks
    while len(s)>=length:
AttributeError: tmpValue instance has no attribute '__len__'
>>> 
Hier der Übeltäter:
http://audaxxx.de/functional-0.2.tar.gz
epsilon
User
Beiträge: 71
Registriert: Freitag 20. Juni 2008, 19:48

Montag 25. August 2008, 15:31

Y0Gi hat geschrieben:Taugt es für Tests? Ist es möglich auszugeben, wie oft eine Zeile im Code ausgeführt wurde? So für Coverage-Auswertung?
Falls es nicht geht, wäre es zumindestens sehr einfach umzusetzen. Das Ganze funktioniert so, dass du 'sys.settrace()' eine Funktion/Instanz-Methode übergibst, die Python für jedes trace event mit bestimmten Parametern aufruft. Wenn du statt einer Funktion eine Instanz-Methode übergibst, kannst du logischerweise die Anzahl der Zeilen im Objekt speichern (z.B. mit defaultdict).
Interessanter Link zu dem Thema: http://www.dalkescientific.com/writings ... _code.html


@ bastian.weber: ich würde den CSS-Code lieber direkt in die Report-Datei schreiben, anstatt eine externe CSS-File zu verwenden. So muss sich die CSS-File immer dort befinden, wo der Report gespeichert wird (was in der Regel nicht der Fall ist).
Antworten