[Python-de] Debug-Ausgabe

Stefan Schwarzer sschwarzer at sschwarzer.net
So Dez 21 10:55:51 CET 2014


Hallo Thomas,

On 2014-12-20 21:52, Thomas 'PointedEars' Lahn wrote:
> [X-Post & F'up2 de.comp.lang.python]

Mir fehlt in diesem Posting relativ viel vom Kontext,
deshalb kann es sein, dass ich auf Sachen eingehe, die schon
erledigt sind.

>> Du schriebst am Wed, 17 Dec 2014 13:17:19 +0100:
> 
> Lies und beherzige bitte <http://einklich.net/usenet/zitier>.

Auf welchen der Punkte dort beziehst du dich in diesem
Kontext? :)

>>>> Ist es und tut es aber. Ich benutze z.B. gerne für "transiente"
>>>> Ausgaben (für Tests und zum Prüfen) vollständig ausgerückte
>>>> Ausgabe-Statements (die also ab Spalte 1 stehen). Das fällt bei einem
>>>> einigermaßen
>> ...
>>>> _Geht_ in Python _nicht_.
>>>
>>> debug = True
>>>
>>> if debug:
>>>     statement1
>>>     statement2

Also, das geht in Python schon und ich finde es, je nachdem,
was man untersucht, auch in Ordnung.

>> Ok, und jetzt nochmal in einem "if" innerhalb einer dreifach
>> geschachtelten Schleife, bitte.
>> BTW, in einer Funktion, natürlich.
> 
> <https://en.wikipedia.org/wiki/Moving_the_goalposts>
> 
> Abgesehen davon:
> 
> In Python schreibt man das IMHO nicht so, sondern geht davon aus, dass 
> Funktionen vom Compiler inlined und unnötige Aufrufe wegoptimiert werden 
> können.

Zumindest in CPython, also der meistverwendeten
Implementierung, wird nur extrem wenig "wegoptimiert". (Zum
Teil liegt das auch daran, dass sich in Python noch sehr
viel zur Laufzeit verändern lässt. Ich will hier nicht
abschweifen; bei Interesse kann ich mehr dazu schreiben.)

Aber selbst wenn der Compiler mehr machen würde/könnte,
würde ich eher davon abraten, Optimierungsempfehlungen an
einzelnen Code-Schnipseln festzumachen. Auch darauf kann
ich bei Interesse ausführlicher eingehen. :)

> Diesen Ansatz empfehle ich auch für andere Programmiersprachen – 
> optimal natürlich als Präprozessor-Makro.  Daher stellt sich das Problem 
> erst gar nicht:
> 
> from sys import stderr
> 
> debug_level=2
> 
> def dmsg (*args, **kwargs):
>     if getattr(kwargs, 'min_level', None) is None:

Da `kwargs` ein Mapping ist, meintest du wahrscheinlich

  if kwargs.pop('min_level', None) is None:

>         kwargs['min_level'] = 1

Zusammengefasst, also inklusive des `if`, könnte man das
übrigens auch als

  kwargs.setdefault('min_level', 1)

schreiben. :-)

An sich würde ich aber gar nicht `kwargs` modifizieren,
sondern den Wert herausziehen:

  min_level = kwargs.pop('min_level', 1)

und dann `min_level` weiterverwenden. Dann brauchst du
weiter unten auch das `del` nicht.

>     if not hasattr(kwargs, 'file'):
>         kwargs['file'] = stderr
> 
>     if debug_level >= kwargs['min_level']:
>         del kwargs['min_level']
>         print(*args, **kwargs)

> for …:
>     for …:
>         for …:
>             dmsg("foo", min_level=1)
> 
> Abgesehen davon: Wer in seinem Code eine dreifach verschachtelte Schleife 
> *direkt* stehen hat, macht sehr wahrscheinlich etwas fhcsla.  Denn er hat es 
> wahrscheinlich versäumt, seinen Code mittels Subroutinen (in Python und 
> Shell: Funktionen; in Python zusätzlich: Methoden) zu strukturieren.

Das kommt drauf an. Wenn zum Beispiel in numerischem Code
über ein dreidimensionales Array iteriert wird, ist die
dreifach verschachtelte Schleife - je nach Kontext - die
"natürliche" Vorgehensweise. Ich gebe dir zwar insofern
recht, dass eine dreifach verschachtelte Schleife ein
"Warnsignal" ("code smell") ist, aber letztlich hängt es von
der Verständlichkeit des konkreten Codes ab, ob oder wie man
es anders machen sollte.

Viele Grüße
Stefan


Mehr Informationen über die Mailingliste python-de