Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Zeitabstand ermitteln (datetime)

781 views
Skip to first unread message

Maik Prinz

unread,
May 10, 2005, 8:15:20 AM5/10/05
to
Hallo,

ich versuche gerade mit Datum+Zeit den jeweils größten und kleinsten
Zeitabstand zu ermitteln. Dafür stehen mir jedoch nur Strings in diesem
Format zur Verfügung:

'Tue, 11 May 2004 11:13:30 +0200'
'Tue, 11 May 2004 11:43:36 +0200'
Ergebnis z.B.: Der Zeitabstand beträgt 30:06 Minuten

'Tue, 11 May 2004 11:43:36 +0200'
'Wed, 12 May 2004 14:06:33 +0200'
Ergebnis z.B.: Der Zeitabstand beträgt: 1 Tag 2:22,57 Stunden

Für Berechnungen bzw. Zeitabstände benötige ich daraus aber AFAIK den Wert
in (Milli?)sekunden seit 1.1.??, um daraus "> als" bzw. "< als" zu
ermitteln und wieder in ein Datumsformat umzuwandeln. Entscheidend ist
natürlich auch, dass die jeweilige Zeitzone mit einbezogen wird.
Aus Perl sind mir dafür gewisse Funktionen bekannt. Aber wie lässt sich
derartiges mit Python realisieren?

Das einzige , was ich bei meinen bisherigen Recherchen finden konnte war:
datetime(year, month, day[, hour[, minute[, second[, microsecond[,tzinfo]]]]])
wozu mir aber leider ein paar Beispiele fehlen, um daraus den praktischen
Nutzen zu entnehmen. Deshalb hoffe ich nun von Euch auf den richtige Weg
gebracht zu werden.

TIA!


cu, Maik
--
250+ 3D Wallpaper: http://www.2prinz.de

40tude Dialog - Free Windows-Newsreader
Download: http://www.40tude.com/dialog/

Mirko Dziadzka

unread,
May 10, 2005, 9:12:10 AM5/10/05
to
Maik Prinz <2pr...@gmx.de> wrote:
> Hallo,
>
> ich versuche gerade mit Datum+Zeit den jeweils größten und kleinsten
> Zeitabstand zu ermitteln. Dafür stehen mir jedoch nur Strings in diesem
> Format zur Verfügung:
>
> 'Tue, 11 May 2004 11:13:30 +0200'

IIRC kannst du mit time.strptime() sowas wieder parsen.

Mirko

Ralf Wachinger

unread,
May 10, 2005, 12:12:26 PM5/10/05
to
Maik Prinz schrieb:

> ich versuche gerade mit Datum+Zeit den jeweils größten und kleinsten
> Zeitabstand zu ermitteln. Dafür stehen mir jedoch nur Strings in diesem
> Format zur Verfügung:
>
> 'Tue, 11 May 2004 11:13:30 +0200'
> 'Tue, 11 May 2004 11:43:36 +0200'
> Ergebnis z.B.: Der Zeitabstand beträgt 30:06 Minuten
>
> 'Tue, 11 May 2004 11:43:36 +0200'
> 'Wed, 12 May 2004 14:06:33 +0200'
> Ergebnis z.B.: Der Zeitabstand beträgt: 1 Tag 2:22,57 Stunden
>
> Für Berechnungen bzw. Zeitabstände benötige ich daraus aber AFAIK den Wert
> in (Milli?)sekunden seit 1.1.??, um daraus "> als" bzw. "< als" zu
> ermitteln und wieder in ein Datumsformat umzuwandeln. Entscheidend ist
> natürlich auch, dass die jeweilige Zeitzone mit einbezogen wird.
> Aus Perl sind mir dafür gewisse Funktionen bekannt. Aber wie lässt sich
> derartiges mit Python realisieren?

Also das Parsen speziell von Date-Headern mit Berücksichtigung aller
Eigenheiten inklusive Offset geht mit den folgenden Utility-Funktionen
aus dem Modul email.Utils. Die strptime-Funktion nützt nichts, weil sie
nicht speziell auf Date-Header-Formate eingeht. Für die Berechnung und
Ausgabe der Zeitdifferenzen verwendest Du ein Timedelta-Objekt aus dem
Modul datetime. Die strftime-Funktionen vom Modul time oder die
strftime-Methoden der Date-/Time-/Datetime-Objekte nützen wenig, weil
sie für Datums-Zeiten gedacht sind.

import datetime, email.Utils
sekunden1 = email.Utils.mktime_tz(email.Utils.parsedate_tz('Tue, 11 May 2004 11:43:36 +0200'))
sekunden2 = email.Utils.mktime_tz(email.Utils.parsedate_tz('Wed, 12 May 2004 14:06:33 +0200'))
zeitdifferenzstring = str(datetime.timedelta(seconds = sekunden2 - sekunden1))
print "Der Zeitabstand beträgt %s Stunden" % zeitdifferenzstring.replace("day", "Tag")

Wenn Du die Date-Header noch schön lesbar immer in lokaler Zeit
(bei uns MEZ/MES) ausgeben willst:

import time
time.strftime("%d.%m.%Y, %H:%M:%S", time.localtime(sekunden1))
time.strftime("%d.%m.%Y, %H:%M:%S", time.localtime(sekunden2))

Maik Prinz

unread,
May 10, 2005, 5:29:23 PM5/10/05
to
* am Di, 10. Mai. 2005 um 18:12 war von Ralf Wachinger zu lesen...
> Maik Prinz schrieb:
>> [Zeitabstand Date-Headern ermitteln]
[...]

> import datetime, email.Utils
> sekunden1 = email.Utils.mktime_tz(email.Utils.parsedate_tz('Tue, 11 May 2004 11:43:36 +0200'))
> sekunden2 = email.Utils.mktime_tz(email.Utils.parsedate_tz('Wed, 12 May 2004 14:06:33 +0200'))
> zeitdifferenzstring = str(datetime.timedelta(seconds = sekunden2 - sekunden1))
> print "Der Zeitabstand beträgt %s Stunden" % zeitdifferenzstring.replace("day", "Tag")

Danke Ralf! Das funktioniert schon mal Klasse. Ich hätte nicht unbedingt
erwartet, dass Du mich gleich mit so viel Informationen versorgst. ;-)
Ich bin erstaunt, das anscheinend nicht mal die Zeitzone Probleme macht.
BTW: Sortierst Du die Datensätze vor dem einlesen nochmal nach Datum?

> Wenn Du die Date-Header noch schön lesbar immer in lokaler Zeit
> (bei uns MEZ/MES) ausgeben willst:
> import time
> time.strftime("%d.%m.%Y, %H:%M:%S", time.localtime(sekunden1))
> time.strftime("%d.%m.%Y, %H:%M:%S", time.localtime(sekunden2))

Super, daran hatte ich jetzt noch gar nicht gedacht. Danke nochmal! :-)
Jetzt muß ich diese Funktionen *nur* noch an geeigneter Stelle im Skript
verankern. ;-)


cu, Maik
--
250+ 3D Wallpaper: http://www.2prinz.de
40tude Dialog - Free Windows-Newsreader
Download: http://www.40tude.com/dialog/

NG: news:de.comm.software.40tude-dialog

Ralf Wachinger

unread,
May 10, 2005, 8:46:28 PM5/10/05
to
Maik Prinz schrieb:

>> import datetime, email.Utils
>> sekunden1 = email.Utils.mktime_tz(email.Utils.parsedate_tz('Tue, 11 May 2004 11:43:36 +0200'))
>> sekunden2 = email.Utils.mktime_tz(email.Utils.parsedate_tz('Wed, 12 May 2004 14:06:33 +0200'))
>> zeitdifferenzstring = str(datetime.timedelta(seconds = sekunden2 - sekunden1))
>> print "Der Zeitabstand beträgt %s Stunden" % zeitdifferenzstring.replace("day", "Tag")
>
> Danke Ralf! Das funktioniert schon mal Klasse. Ich hätte nicht unbedingt
> erwartet, dass Du mich gleich mit so viel Informationen versorgst. ;-)

Wir haben doch auch schon in Dcs4-d über das Rüberwachsenlassen von
Code-Brocken geschrieben :o)

> Ich bin erstaunt, das anscheinend nicht mal die Zeitzone Probleme macht.

Im Email-Modul und seinen Untermodulen gibt es eine Menge sehr
nützlicher Funktionen, um mit Email- und News-Artikeln zu arbeiten. Ich
benutze etliches daraus.

> BTW: Sortierst Du die Datensätze vor dem einlesen nochmal nach Datum?

Nein, erst vor der Ausgabe. Aber das kann man eh nicht als Maßstab
nehmen, weil mein Programm anders arbeitet.

Aber natürlich muss man vor dem Vergleichen von Zeiten die Datensätze
nach Zeit sortieren, was sowohl bei Sekundenzeiten als auch bei
Datetime-Objekten leicht ist.

Bei mir ist es jedenfalls folgendermaßen, um mal das Prinzip zu zeigen:

mids = sorted(self.newsdaten, key = lambda mid: self.newsdaten[mid].sekundenzeit)

self.newsdaten ist das Dictionary, das alle Artikeldaten enthält, mit
den Message-IDs als Schlüssel. Hinter sekundenzeit versteckt sich die
Umwandlung wie im Code oben. Die Funktion sorted gibt eine sortierte
Liste der Message-IDs zurück, mit der ich dann die Zeitspannen zwischen
den Artikeln errechnen kann.

Mit den Objekten im Modul datetime kann man sich übrigens eine Menge
Programmier-Arbeit sparen. Leider war das zu der Zeit, als ich mein
Programm geschrieben hatte, noch nicht in der Python-Distribution dabei.
Erst der neue Code, den ich jetzt schreibe, kann davon profitieren.

> Super, daran hatte ich jetzt noch gar nicht gedacht. Danke nochmal! :-)
> Jetzt muß ich diese Funktionen *nur* noch an geeigneter Stelle im Skript
> verankern. ;-)

Noch ein Tip um ans Obige anzuschließen: Du kannst die Sekundenzeiten
gleich in Datetime-Objekte speichern, dann sparst Du Dir den Import des
Moduls time (das Modul datetime kann man praktisch als modernere
OOP-Version sehen) und kannst mit den Datetime- und Timedelta-Objekten
direkt rechnen. Leider haben Timedelta-Objekte im Gegensatz zu
Datetime-Objekten keine strftime-Methode, sondern nur eine Ausgabeform:

zeit1 = datetime.datetime.fromtimestamp(sekunden1)
zeit2 = datetime.datetime.fromtimestamp(sekunden2)
differenzzeit = zeit2 - zeit1
print zeit1.strftime("%d.%m.%Y, %H:%M:%S")
print zeit2.strftime("%d.%m.%Y, %H:%M:%S")
print "Der Zeitabstand beträgt %s Stunden" % str(differenzzeit).replace("days", "Tage").replace("day", "Tag")

Michael Steinmetz

unread,
May 11, 2005, 9:30:31 AM5/11/05
to
Maik Prinz <2pr...@gmx.de> wrote:
> * am Di, 10. Mai. 2005 um 18:12 war von Ralf Wachinger zu lesen...

> > time.strftime("%d.%m.%Y, %H:%M:%S", time.localtime(sekunden2))

> Super, daran hatte ich jetzt noch gar nicht gedacht. Danke nochmal! :-)
> Jetzt muß ich diese Funktionen *nur* noch an geeigneter Stelle im Skript
> verankern. ;-)

Willst Du jetzt doch noch eine Statistik von Postingzeiten einbauen? ;-)


Gruss,
St1
--
#!/usr/bin/python
fa=3532461934402770121272604978198464368671197400197625023649303468776121253679423200058547956528088349
fb=7925869954478333033347085841480059687737975857364219960734330341455767872818152135381409304740185467
rsa=fa*fb; print "RSA%d = %d = %d * %d " % (len("%d" % rsa), rsa, fa, fb)

Maik Prinz

unread,
May 11, 2005, 1:31:20 PM5/11/05
to
* am Mi, 11. Mai. 2005 um 15:30 war von Michael Steinmetz zu lesen...

> Maik Prinz <2pr...@gmx.de> wrote:
>> * am Di, 10. Mai. 2005 um 18:12 war von Ralf Wachinger zu lesen...
>>> time.strftime("%d.%m.%Y, %H:%M:%S", time.localtime(sekunden2))
>> Super, daran hatte ich jetzt noch gar nicht gedacht. Danke nochmal! :-)
>> Jetzt muß ich diese Funktionen *nur* noch an geeigneter Stelle im Skript
>> verankern. ;-)
> Willst Du jetzt doch noch eine Statistik von Postingzeiten einbauen? ;-)

Arrgh erwischt, aber keine Angst, es geht hier nicht um personenbezogene
Postingzeiten sondern darum, wie lang war die größte/kleinste Pause
zwischen 2 Artikeln in einem Monat allgemein war. :-)

Maik Prinz

unread,
May 11, 2005, 4:27:24 PM5/11/05
to
* am Mi, 11. Mai. 2005 um 2:46 war von Ralf Wachinger zu lesen...
> Maik Prinz schrieb:
[Viele wertvolle Codeabschnitte]

>> Danke Ralf! Das funktioniert schon mal Klasse. Ich hätte nicht unbedingt
>> erwartet, dass Du mich gleich mit so viel Informationen versorgst. ;-)
> Wir haben doch auch schon in Dcs4-d über das Rüberwachsenlassen von
> Code-Brocken geschrieben :o)

Es ist bloß nicht jeder gleich so großzügig mit der Weitergabe von so
vollständigen "Code-Brocken". Bei Dir war es jedoch naheliegend, da Du
ja bereits derartige Routinen entwickelt und bei dir am werkeln hast. :)

BTW mache ich Fortschritte mit der Implementierung. Kannst Du folgende
Daten in dcs4-d für den Zeitraum bis Heute bestätigen?:

Der längste Zeitabstand beträgt 11:34:33 Stunden
vom 10.05.2005, 23:46:42 bis 11.05.2005, 11:21:15
Der kürzeste Zeitabstand beträgt 0:00:01 Stunden
vom 01.05.2005, 10:12:49 bis 01.05.2005, 10:12:50

Gleiches möchte ich dann anhand der References noch für die kürzeste
Zeit bis zu einer Antwort bewerkstelligen.

>> Ich bin erstaunt, das anscheinend nicht mal die Zeitzone Probleme macht.
> Im Email-Modul und seinen Untermodulen gibt es eine Menge sehr
> nützlicher Funktionen, um mit Email- und News-Artikeln zu arbeiten. Ich
> benutze etliches daraus.

Das werde ich mir bestimmt auch noch mal genauer anschauen. :-)

>> BTW: Sortierst Du die Datensätze vor dem einlesen nochmal nach Datum?
> Nein, erst vor der Ausgabe. Aber das kann man eh nicht als Maßstab
> nehmen, weil mein Programm anders arbeitet.

Daran hapert es bei mir gegenwärtig noch. Aktuell entspricht die
Reihenfolge derer, wie die Daten vom Server geholt werden. :-/

[...]

Danke auch für Deine weiteren Tipps und Empfehlungen! :-))

Maik Prinz

unread,
May 12, 2005, 8:45:25 AM5/12/05
to
* am Mi, 11. Mai. 2005 um 22:27 war von Maik Prinz zu lesen...

> BTW mache ich Fortschritte mit der Implementierung. Kannst Du folgende
> Daten in dcs4-d für den Zeitraum bis Heute bestätigen?:
> Der längste Zeitabstand beträgt 11:34:33 Stunden
> vom 10.05.2005, 23:46:42 bis 11.05.2005, 11:21:15
> Der kürzeste Zeitabstand beträgt 0:00:01 Stunden
> vom 01.05.2005, 10:12:49 bis 01.05.2005, 10:12:50
> Gleiches möchte ich dann anhand der References noch für die kürzeste
> Zeit bis zu einer Antwort bewerkstelligen.
~~~~~~~~~~~~~~~~~~~~~~~~~
Kannst Du *das* jetzt bitte auch noch vergleichen?:

Den schnellsten FU'p gab es in 0:03:22 Stunden,
vom 05.05.2005, 22:34:37 bis 05.05.2005, 22:37:59


THX, Maik


--
250+ 3D Wallpaper: http://www.2prinz.de

Maik Prinz

unread,
May 12, 2005, 5:02:58 PM5/12/05
to
* am Mi, 11. Mai. 2005 um 22:27 war von Maik Prinz zu lesen...
> Der kürzeste Zeitabstand beträgt 0:00:01 Stunden
> vom 01.05.2005, 10:12:49 bis 01.05.2005, 10:12:50

Da dies IMO wenig Sinn macht, da viele User ihre Artikel Gruppenweise
versenden, habe ich nun mal den kürzesten Zeitabstand von 2 Artikeln
verschiedener Poster gemessen und komme in dcs4-d zu folgendem Ergebnis:

Der kürzeste Zeitabstand beträgt 0:00:05 Stunden,
vom 11.05.2005, 20:51:38 bis 11.05.2005, 20:51:43

:-)


cu, Maik
--
250+ 3D Wallpaper: http://www.2prinz.de

Ralf Wachinger

unread,
May 12, 2005, 7:35:16 PM5/12/05
to
Maik Prinz schrieb:

> Es ist bloß nicht jeder gleich so großzügig mit der Weitergabe von so
> vollständigen "Code-Brocken". Bei Dir war es jedoch naheliegend, da Du
> ja bereits derartige Routinen entwickelt und bei dir am werkeln hast. :)

Es ist ja letztendlich fad, wenn man immer nur ohne Austausch daheim am
Computer werkelt, außerdem leben die Netze vom Mitmachen vieler Leute.
Ich bin immer noch am Werkeln. Das Ganze ist sehr interessant, besonders
weil ich auch immer mehr von Python lerne, obwohl ich schon so viel
weiß. Nun habe ich besonders die Iterators, Itertools, Generators und
Generator Expressions ins Auge gefasst, die bieten ein pfiffiges
Konzept.

> BTW mache ich Fortschritte mit der Implementierung. Kannst Du folgende
> Daten in dcs4-d für den Zeitraum bis Heute bestätigen?:
>
> Der längste Zeitabstand beträgt 11:34:33 Stunden
> vom 10.05.2005, 23:46:42 bis 11.05.2005, 11:21:15
> Der kürzeste Zeitabstand beträgt 0:00:01 Stunden
> vom 01.05.2005, 10:12:49 bis 01.05.2005, 10:12:50

Bingo! Ich habe bei mir die gleichen Zeiten:

Zeitspanne ! Artikelzeit ! Folgeartikelzeit
----------------------------------------------------------------------
11:34:33 h ! 10.05.05 23:46:42 ! 11.05.05 11:21:15
...

Bei mir gehts noch weiter, da mein Programm auch mehrere größte Zeiten
ausrechnen kann, sowie mehrere kleinste Zeiten.


Zeitspanne ! Auftreten
----------------------------------------------------------------------
00:00:01 h ! 1x
...

Bei den kürzesten Zeiten interessieren mich nicht die genauen
Zeitangaben, weil es viele kurze Zeiten geben kann (wenn Leute
Posting-Paket schicken in High-Traffic-Gruppen), darum zähle ich deren
Auftreten, und zwar zwischen verschiedenen Postern.

> Gleiches möchte ich dann anhand der References noch für die kürzeste
> Zeit bis zu einer Antwort bewerkstelligen.

Da kann ich Dir schon mal die Ergebnisse meines Programms zeigen:

! Antwortzeit ! Antworter
----------------------------------------------------------------------
Durchschnittlich ! 08:40:25 h
Kürzeste ! 00:00:54 h ! Enrico Bauer
Längste ! 5 d 20:03:57 h ! Maik Prinz

>> Im Email-Modul und seinen Untermodulen gibt es eine Menge sehr
>> nützlicher Funktionen, um mit Email- und News-Artikeln zu arbeiten. Ich
>> benutze etliches daraus.
>
> Das werde ich mir bestimmt auch noch mal genauer anschauen. :-)

Da wirst Du zu tun haben bei der Vielfältigkeit des Modul-Pakets.

>> Nein, erst vor der Ausgabe. Aber das kann man eh nicht als Maßstab
>> nehmen, weil mein Programm anders arbeitet.
>
> Daran hapert es bei mir gegenwärtig noch. Aktuell entspricht die
> Reihenfolge derer, wie die Daten vom Server geholt werden. :-/

Zum Sortieren gibt es ja besonders in V2.4 mehrere Wege. Es kommt
natürlich auch darauf an, wie die Daten strukturiert sind.

Ralf Wachinger

unread,
May 12, 2005, 8:24:41 PM5/12/05
to
Maik Prinz schrieb:

> Kannst Du *das* jetzt bitte auch noch vergleichen?:
>
> Den schnellsten FU'p gab es in 0:03:22 Stunden,
> vom 05.05.2005, 22:34:37 bis 05.05.2005, 22:37:59

Oha, das stimmt nicht mit meiner Auswertung überein. Ich sehe auch, wie
verschieden wir unsere Auswertungen informationsmäßig gestalten, da wir
offensichtlich andere Schwerpunkte haben, was wir sehen wollen (jetzt
nicht auf die unterschiedlichen Zeitabstände bezogen gemeint).

Ich habe mein Ergebnis im Posting
<355db023fdb1180d...@wachinger.fqdn.th-h.de> gebracht,
später als Deines, hatte Deines da aber noch nicht geladen und gelesen.
Bitte antworte mir doch im verwiesenen Posting, um eine Verzweigung
unserer Diskussion zu vermeiden.

Ralf Wachinger

unread,
May 12, 2005, 8:24:32 PM5/12/05
to
Maik Prinz schrieb:

>> Der kürzeste Zeitabstand beträgt 0:00:01 Stunden
>> vom 01.05.2005, 10:12:49 bis 01.05.2005, 10:12:50
>
> Da dies IMO wenig Sinn macht, da viele User ihre Artikel Gruppenweise
> versenden, habe ich nun mal den kürzesten Zeitabstand von 2 Artikeln
> verschiedener Poster gemessen und komme in dcs4-d zu folgendem Ergebnis:
>
> Der kürzeste Zeitabstand beträgt 0:00:05 Stunden,
> vom 11.05.2005, 20:51:38 bis 11.05.2005, 20:51:43

Auch das stimmt nicht mit meiner Auswertung überein.

Also auch dieses Posting habe ich erst geladen und gelesen, als ich
meines schon abgeschickt hatte. Also auch hier bitte im Posting
<355db023fdb1180d...@wachinger.fqdn.th-h.de> antworten.

Maik Prinz

unread,
May 13, 2005, 1:22:22 PM5/13/05
to
* am Fr, 13. Mai. 2005 um 1:35 war von Ralf Wachinger zu lesen...
> Maik Prinz schrieb:
[...]

>> BTW mache ich Fortschritte mit der Implementierung. Kannst Du folgende
>> Daten in dcs4-d für den Zeitraum bis Heute bestätigen?:
>>
>> Der längste Zeitabstand beträgt 11:34:33 Stunden
>> vom 10.05.2005, 23:46:42 bis 11.05.2005, 11:21:15
>> Der kürzeste Zeitabstand beträgt 0:00:01 Stunden
>> vom 01.05.2005, 10:12:49 bis 01.05.2005, 10:12:50
> Bingo! Ich habe bei mir die gleichen Zeiten:
> Zeitspanne ! Artikelzeit ! Folgeartikelzeit
> ----------------------------------------------------------------------
> 11:34:33 h ! 10.05.05 23:46:42 ! 11.05.05 11:21:15
> ...

Na Super, das ist doch wenigstens etwas ...

> Bei mir gehts noch weiter, da mein Programm auch mehrere größte Zeiten
> ausrechnen kann, sowie mehrere kleinste Zeiten.
> Zeitspanne ! Auftreten
> ----------------------------------------------------------------------
> 00:00:01 h ! 1x
> ...
> Bei den kürzesten Zeiten interessieren mich nicht die genauen
> Zeitangaben, weil es viele kurze Zeiten geben kann (wenn Leute
> Posting-Paket schicken in High-Traffic-Gruppen), darum zähle ich deren
> Auftreten, und zwar zwischen verschiedenen Postern.

Deshalb habe ich, wie im anderen Artikel geschrieben, hierbei nur
Zeitabstände von Artikeln verschiedener Poster verglichen (aktuell 5s).

>> Gleiches möchte ich dann anhand der References noch für die kürzeste
>> Zeit bis zu einer Antwort bewerkstelligen.
> Da kann ich Dir schon mal die Ergebnisse meines Programms zeigen:
> ! Antwortzeit ! Antworter
> ----------------------------------------------------------------------
> Durchschnittlich ! 08:40:25 h
> Kürzeste ! 00:00:54 h ! Enrico Bauer

Kannst Du das verifizieren? Wann soll den das gewesen sein? IMO reichen
54sek oft nicht mal zu lesen eines Artikels. Ich habe jetzt folgendes:
,----
| Die schnellste Antwort gab es in 0:02:36 Stunden von Maik Prinz
| auf M-ID: t8ny3yopticy$.d...@notforspam.news.arcor.de
| vom 13.05.2005, 17:47:12 bis 13.05.2005, 17:49:48
`----
als schnellste Antwort ausmachen können. :)

> Längste ! 5 d 20:03:57 h ! Maik Prinz

Boah eh, das war ja wirlich ich, und dann ließ auch noch ein Antwort auf
einen Deiner Artikel so lange auf sich warten. ;-)
,----
| Die späteste Antwort gab es in 5 Tags, 20:03:57 Stunden von Maik Prinz
| auf M-ID: 267b156fb76d05b2...@wachinger.fqdn.th-h.de
| vom 03.05.2005, 16:00:11 bis 09.05.2005, 12:04:08
`----

BTW: wie kann ich aus Tags automagisch Tage machen? Es resultiert ja
AFAICS aus Day(s). Ich bin gleichzeitig auch schon am überlegen, wie ich
z.B. aus "00:00:54 Stunden" am einfachsten "54 Sekunden" machen kann.
Da der String immer eine konstante Länge hat, ware z.B.:

if string[0:4]=='00:00':
string = string[-2:] + ' Sekunden'
elif string[0:2]=='00':
string = string[-4:] + ' Minuten'
else:
string = string + ' Stunden'

... eine Möglichkeit!?

>>> Im Email-Modul und seinen Untermodulen gibt es eine Menge sehr
>>> nützlicher Funktionen, um mit Email- und News-Artikeln zu arbeiten. Ich
>>> benutze etliches daraus.
>> Das werde ich mir bestimmt auch noch mal genauer anschauen. :-)
> Da wirst Du zu tun haben bei der Vielfältigkeit des Modul-Pakets.

Dann mach ich das mal lieber wenn ich ganz viiiiieeeeel Zeit habe. ;-)

[Datensätze sortieren]


>> Daran hapert es bei mir gegenwärtig noch. Aktuell entspricht die
>> Reihenfolge derer, wie die Daten vom Server geholt werden. :-/
> Zum Sortieren gibt es ja besonders in V2.4 mehrere Wege. Es kommt
> natürlich auch darauf an, wie die Daten strukturiert sind.

Ich habe mal versucht negative Werte abzufangen, und hatte dabei keinen
Treffer. Demnach sollte die Reihenfolge doch so stimmen.


THX, Maik

Ralf Wachinger

unread,
May 13, 2005, 8:31:24 PM5/13/05
to
Maik Prinz schrieb:

>> Bingo! Ich habe bei mir die gleichen Zeiten:
>> Zeitspanne ! Artikelzeit ! Folgeartikelzeit
>> ----------------------------------------------------------------------
>> 11:34:33 h ! 10.05.05 23:46:42 ! 11.05.05 11:21:15
>> ...
>
> Na Super, das ist doch wenigstens etwas ...

Gut, dann ist das geklärt.

> Deshalb habe ich, wie im anderen Artikel geschrieben, hierbei nur
> Zeitabstände von Artikeln verschiedener Poster verglichen (aktuell 5s).

Wie ich bei den kürzesten Zeiten, also ist das auch geklärt

>> Da kann ich Dir schon mal die Ergebnisse meines Programms zeigen:
>> ! Antwortzeit ! Antworter
>> ----------------------------------------------------------------------
>> Durchschnittlich ! 08:40:25 h
>> Kürzeste ! 00:00:54 h ! Enrico Bauer
>
> Kannst Du das verifizieren? Wann soll den das gewesen sein? IMO reichen
> 54sek oft nicht mal zu lesen eines Artikels. Ich habe jetzt folgendes:

Verifiziert! Ich habe verschiedene Testauswertung von mir mit den
Artikeln in meinem Newsreader verglichen, und mein Programm
statistiziert richtig. Das war eine Selbstantwort des oben Genannten,
und eine solche schließe ich nicht von der Zählung aus - sollte ich
wahrscheinlich doch tun...

> ,----
> | Die schnellste Antwort gab es in 0:02:36 Stunden von Maik Prinz
> | auf M-ID: t8ny3yopticy$.d...@notforspam.news.arcor.de
> | vom 13.05.2005, 17:47:12 bis 13.05.2005, 17:49:48
> `----
> als schnellste Antwort ausmachen können. :)

Wenn Du Selbstantworten ausschließt, dann Bingo! Ich habe es bei mir mal
auf den 13. eingegrenzt:

Kürzeste ! 00:02:36 h ! 13.05.05 17:47:12 ! 13.05.05 17:49:48

Übrigens habe ich nun eine Option eingebaut, die Namen in Verbindung mit
Uhrzeiten wegzulassen - Du weißt schon :o)

>> Längste ! 5 d 20:03:57 h ! Maik Prinz
>
> Boah eh, das war ja wirlich ich, und dann ließ auch noch ein Antwort auf
> einen Deiner Artikel so lange auf sich warten. ;-)

Allerdings kann mein Programm Antwortzeiten, die auf unendlich zugehen,
nicht statistizieren ;o)

> BTW: wie kann ich aus Tags automagisch Tage machen? Es resultiert ja
> AFAICS aus Day(s). Ich bin gleichzeitig auch schon am überlegen, wie ich
> z.B. aus "00:00:54 Stunden" am einfachsten "54 Sekunden" machen kann.
> Da der String immer eine konstante Länge hat, ware z.B.:
>
> if string[0:4]=='00:00':
> string = string[-2:] + ' Sekunden'
> elif string[0:2]=='00':
> string = string[-4:] + ' Minuten'
> else:
> string = string + ' Stunden'
>
> ... eine Möglichkeit!?

Ich kann Dir das Rezept anbieten, das ich schon vor Datetime-Zeiten
angewandt habe, ein bisschen angepasst auf Timedelta-Objekte. Die
folgende Funktion ersetzt die eingebaute Stringausgabe. Das müsste
dem hinkommen, was Du offenbar möchtest:

def Zeitstring(delta):
ausgabe = ""
stunden = delta.seconds // 3600
minuten = (delta.seconds - (stunden * 3600)) // 60
sekunden = delta.seconds - (stunden * 3600) - (minuten * 60)
if delta.days: ausgabe += "%d T." % delta.days
if stunden: ausgabe += " %d Std." % stunden
if minuten: ausgabe += " %d Min." % minuten
if sekunden: ausgabe += " %d Sek." % sekunden
return ausgabe

>> Zum Sortieren gibt es ja besonders in V2.4 mehrere Wege. Es kommt
>> natürlich auch darauf an, wie die Daten strukturiert sind.
>
> Ich habe mal versucht negative Werte abzufangen, und hatte dabei keinen
> Treffer. Demnach sollte die Reihenfolge doch so stimmen.

Also ich habe jetzt auswertungsmäßig drin:
1. Die durchschnittliche, die kürzteste, die längste Antwortzeit
2. Die Negativantwortzeiten, falls jemand eine falsche Zeit benutzt
3. Der erste und der letzte Artikel im Auswertungszeitraum
4. Die x längsten und die x kürzesten Zeitspannen

Und für Threads:
1. Die postingmäßig größten Threadbäume
2. Die Personen und in wie vielen Threadbäumen sie sind
3. Die neuen Threads
4. Die Ersteller der neuen Threads
5. Die längsten Teilthreads mit einigen Daten

Das mit dem Threading war eine saumäßige Arbeit, allerdings war es auch
eine Herausforderung, die ich gemeistert habe.

Maik Prinz

unread,
May 14, 2005, 9:30:48 AM5/14/05
to
* am Sa, 14. Mai. 2005 um 2:31 war von Ralf Wachinger zu lesen...
[...]

>>> Kürzeste ! 00:00:54 h ! Enrico Bauer
>>
>> Kannst Du das verifizieren? Wann soll den das gewesen sein? IMO reichen
>> 54sek oft nicht mal zu lesen eines Artikels. Ich habe jetzt folgendes:
> Verifiziert! Ich habe verschiedene Testauswertung von mir mit den
> Artikeln in meinem Newsreader verglichen, und mein Programm
> statistiziert richtig. Das war eine Selbstantwort des oben Genannten,
> und eine solche schließe ich nicht von der Zählung aus - sollte ich
> wahrscheinlich doch tun...

ACK & dito. :-)

>> ,----
>>| Die schnellste Antwort gab es in 0:02:36 Stunden von Maik Prinz
>>| auf M-ID: t8ny3yopticy$.d...@notforspam.news.arcor.de
>>| vom 13.05.2005, 17:47:12 bis 13.05.2005, 17:49:48
>> `----
>> als schnellste Antwort ausmachen können. :)
> Wenn Du Selbstantworten ausschließt, dann Bingo!

Bingo! :) Es macht ansonsten IMO wenig Sinn, zu messen wie schnell
jemand auf sich selbst antwortet weil er z.B. im vorhergehenden Artikel
etwas vergessen hat. Da ich in der Routine ohnehin schon auf "Ingrids"
geprüft hatte, konnte ich dies auch gleich weiter nutzen. :-)

> Allerdings kann mein Programm Antwortzeiten, die auf unendlich zugehen,
> nicht statistizieren ;o)

... nun wollen wir mal nicht übertreiben. ;-)
Enrico hat da allerdings seine speziellen Wünsche für die Jahres-Stats.

>> BTW: wie kann ich aus Tags automagisch Tage machen?

Oops, da habe ich doch glatt was überlesen:
| [...] str(differenzzeit).replace("days", "Tage").replace("day", "Tag")

>> Ich bin gleichzeitig auch schon am überlegen, wie ich
>> z.B. aus "00:00:54 Stunden" am einfachsten "54 Sekunden" machen kann.
>> Da der String immer eine konstante Länge hat, ware z.B.:
>>
>> if string[0:4]=='00:00':
>> string = string[-2:] + ' Sekunden'
>> elif string[0:2]=='00':
>> string = string[-4:] + ' Minuten'
>> else:
>> string = string + ' Stunden'
>>
>> ... eine Möglichkeit!?
> Ich kann Dir das Rezept anbieten, das ich schon vor Datetime-Zeiten
> angewandt habe, ein bisschen angepasst auf Timedelta-Objekte. Die
> folgende Funktion ersetzt die eingebaute Stringausgabe. Das müsste
> dem hinkommen, was Du offenbar möchtest:
> def Zeitstring(delta):
> ausgabe = ""
> stunden = delta.seconds // 3600
> minuten = (delta.seconds - (stunden * 3600)) // 60
> sekunden = delta.seconds - (stunden * 3600) - (minuten * 60)
> if delta.days: ausgabe += "%d T." % delta.days
> if stunden: ausgabe += " %d Std." % stunden
> if minuten: ausgabe += " %d Min." % minuten
> if sekunden: ausgabe += " %d Sek." % sekunden
> return ausgabe

Das war nicht ganz das Gesuchte, brachte mich aber mit diversen
Anpassungen auf den richtigen Weg. Sorry, der Code ist IMO etwas
Overkill:

def Zeitstring(delta):
import string
ausgabe = ""
h = delta.seconds // 3600
stunden = string.zfill(str(delta.seconds // 3600), 2)
m = (delta.seconds - (h * 3600)) // 60
if h: minuten = string.zfill(str((delta.seconds - (h * 3600)) // 60), 2)
else: minuten = str((delta.seconds - (h * 3600)) // 60)
if m: sekunden = string.zfill(str(delta.seconds - (h * 3600) - (m * 60)), 2)
else: sekunden = str(delta.seconds - (h * 3600) - (m * 60))
if delta.days:
if delta.days==1: ausgabe += "%d Tag, " % delta.days
else: ausgabe += "%d Tagen, " % delta.days
if h:
if h==1: ausgabe += "%s:" %stunden + "%s:" %minuten + "%s" %sekunden + " Stunde"
else: ausgabe += "%s:" %stunden + "%s:" %minuten + "%s" %sekunden + " Stunden"
elif m:
if m==1: ausgabe += "%s:" %minuten + "%s" %sekunden + " Minute"
else: ausgabe += "%s:" %minuten + "%s" %sekunden + " Minuten"
elif sekunden:
if sekunden==1: ausgabe += "%s Sekunde" % sekunden
else: ausgabe += "%s Sekunden" % sekunden
return ausgabe

Die Experten wüßten sicherlich, wie man das extrem optimieren könnte. :)
Das Ergebnis ist jetzt jedenfalls automagisch wie folgt aus:

Der kürzeste Zeitabstand beträgt 5 Sekunden,
Der längste Zeitabstand beträgt 11:34:33 Stunden,
Die schnellste Antwort gab es in 2:36 Minuten
Die späteste Antwort gab es nach 5 Tagen, 20:03:57 Stunden

... und entspricht genau meinen Vorstellungen.

> Also ich habe jetzt auswertungsmäßig drin:
> 1. Die durchschnittliche, die kürzteste, die längste Antwortzeit

Da ich nur von Artikel zu Artikel vergleiche, ist die durchschnittliche
Zeit bei mir vorerst nicht drin. Das ist mir persönlich auch nicht ganz
so wichtig.

> 2. Die Negativantwortzeiten, falls jemand eine falsche Zeit benutzt

Habe ich als Kontrollfunktion - aber bisher ohne Treffer. :)

> 3. Der erste und der letzte Artikel im Auswertungszeitraum

IMHO auch eher Geschmackssache und für mich nicht unbedingt von
Interesse.

> 4. Die x längsten und die x kürzesten Zeitspannen

Darin bestand ja auch unser Hauptanliegen, welches jetzt wohl klappt.
Womit ich mich noch schwer tue, ist die Erfassung der Stunde mit den
meisten Postings. Dafür müsste ich dann wohl von jedem einzelnen Artikel
ausgehend die Folgeartikel zählen, solange der Zeitraum von einer Stunde
nicht überschritten ist. Für den höchsten Wert ist dann die Zeit des
ersten Artikels als Anfangszeit, und diese plus einer Stunde als Endzeit
zu ermitteln.

> Und für Threads:
> 1. Die postingmäßig größten Threadbäume
> 2. Die Personen und in wie vielen Threadbäumen sie sind
> 3. Die neuen Threads

Das Problem dabei sind AFAICS z.B kaputte References, die leider keine
Seltenheit sind. Das Problem zeigt sich gerade im laufenden Monat in
dcs4-d im Thread "[Scripting] Neue Funktionen". Jedenfalls macht Dich
Artikel <news:dcs4.05050...@gwaihir.akallabeth.de> zu einem
Threadgründer.

> 4. Die Ersteller der neuen Threads

... wie oben. :-/

> 5. Die längsten Teilthreads mit einigen Daten

Erfasst Du auch Subjektwechsel?

Ralf Wachinger

unread,
May 14, 2005, 6:17:23 PM5/14/05
to
Maik Prinz schrieb:

>> Wenn Du Selbstantworten ausschließt, dann Bingo!
>
> Bingo! :) Es macht ansonsten IMO wenig Sinn, zu messen wie schnell
> jemand auf sich selbst antwortet weil er z.B. im vorhergehenden Artikel
> etwas vergessen hat. Da ich in der Routine ohnehin schon auf "Ingrids"
> geprüft hatte, konnte ich dies auch gleich weiter nutzen. :-)

Dein Ergebnis der schnellsten Antwort von 2:36 Minuten kann ich jetzt
positiv bestätigen.

> ... nun wollen wir mal nicht übertreiben. ;-)
> Enrico hat da allerdings seine speziellen Wünsche für die Jahres-Stats.

Aha, welche sind das denn?

> Oops, da habe ich doch glatt was überlesen:
> | [...] str(differenzzeit).replace("days", "Tage").replace("day", "Tag")

Ja, allerdings es eh besser, man geht von den Timedelta-Datenattributen
statt vom Ergebnis der Str-Funktion für Timedeltas aus.

> Das war nicht ganz das Gesuchte, brachte mich aber mit diversen
> Anpassungen auf den richtigen Weg. Sorry, der Code ist IMO etwas
> Overkill:

> [Code]

Ja, der ist tatsächlich etwas overkillend, aber was solls, Hauptsache,
er funktioniert. Ich hoffe, dass die Timedeltas in Zukunft eine
Strftime-Methode verpasst bekommen.

> Die Experten wüßten sicherlich, wie man das extrem optimieren könnte. :)
> Das Ergebnis ist jetzt jedenfalls automagisch wie folgt aus:
>
> Der kürzeste Zeitabstand beträgt 5 Sekunden,
> Der längste Zeitabstand beträgt 11:34:33 Stunden,
> Die schnellste Antwort gab es in 2:36 Minuten
> Die späteste Antwort gab es nach 5 Tagen, 20:03:57 Stunden
>
> ... und entspricht genau meinen Vorstellungen.

Gut. Mir wäre es zu lang, denn meine Stat produziert mehr Daten, die ich
in Spalten organisiere, da müssen die Texte kürzer sein.

>> Also ich habe jetzt auswertungsmäßig drin:
>> 1. Die durchschnittliche, die kürzteste, die längste Antwortzeit
>
> Da ich nur von Artikel zu Artikel vergleiche, ist die durchschnittliche
> Zeit bei mir vorerst nicht drin. Das ist mir persönlich auch nicht ganz
> so wichtig.

Ich mache das mit einer temporären Zeitspannenliste, wo alle jeweiligen
Zeitspannen gesammelt werden, dann kann man bequem die Werte per max(),
min(), sum() / len() rausziehen.

>> 2. Die Negativantwortzeiten, falls jemand eine falsche Zeit benutzt
>
> Habe ich als Kontrollfunktion - aber bisher ohne Treffer. :)

Gibt derzeit auch keine in Dcs4-d.

>> 4. Die x längsten und die x kürzesten Zeitspannen
>
> Darin bestand ja auch unser Hauptanliegen, welches jetzt wohl klappt.
> Womit ich mich noch schwer tue, ist die Erfassung der Stunde mit den
> meisten Postings. Dafür müsste ich dann wohl von jedem einzelnen Artikel
> ausgehend die Folgeartikel zählen, solange der Zeitraum von einer Stunde
> nicht überschritten ist. Für den höchsten Wert ist dann die Zeit des
> ersten Artikels als Anfangszeit, und diese plus einer Stunde als Endzeit
> zu ermitteln.

Du meinst die Zahlen von Oliver Cromm?

| Meiste Artikel innerhalb 1h:
| 35 Artikel zwischen 25.04, 20:55:44 und 25.04, 21:55:43
| Meiste Artikel innerhalb 24h:
| 155 Artikel zwischen 10.04, 11:14:53 und 11.04, 11:14:52

Da habe ich auch schon drüber nachgedacht. Eine bessere Methode als Du
habe ich auch nicht. Ausgangspunkt ist eine nach Sekundenzeit sortierte
Liste der Artikel. Dürfte verständlich sein, musst Du halt nur auf Dein
spezielles Programm umsetzen:

-------------------------- Code schnipp ------------------------------
def MeisteArtikelInZeitraum(self, stream, kenntext, sekundenzeitraum):
"Berechnet, wann innerhalb eines Zeitraums die meisten Artikel gepostet wurden"

# Ab der Zeit des 'anfangsartikel' meiste Artikel 'maxArtikel'.
anfangsartikel = 0
maxArtikel = 0

newsdatenliste = sorted(self.newsdaten.itervalues(), key = lambda artikel: artikel.sekundenzeit)
for index1, artikel in enumerate(newsdatenliste):
for index2 in xrange(index1 + 1, len(newsdatenliste)):
if newsdatenliste[index2].sekundenzeit - artikel.sekundenzeit < sekundenzeitraum:
if index2 - index1 + 1 > maxArtikel:
maxArtikel = index2 - index1 + 1
anfangsartikel = artikel
else:
break

print >> stream, ""
print >> stream, "Die meisten Artikel innerhalb %s:" % kenntext
print >> stream, " %4d Artikel zwischen %s und %s" \
% (maxArtikel, anfangsartikel.Zeitstring(),
time.strftime("%c", time.localtime(anfangsartikel.sekundenzeit + sekundenzeitraum - 1)))
print >> stream, ""


self.MeisteArtikelInZeitraum(stream, "1 Stunde", 3600)
self.MeisteArtikelInZeitraum(stream, "24 Stunden", 3600 * 24)

-------------------------- Code schnapp ------------------------------

Für April kriege ich das gleiche Ergebnis wie oben, für 01. - 13 Mai:

Die meisten Artikel innerhalb 1 Stunde:
19 Artikel zwischen 02.05.05 22:53:12 und 02.05.05 23:53:11

Die meisten Artikel innerhalb 24 Stunden:
109 Artikel zwischen 01.05.05 23:53:13 und 02.05.05 23:53:12

>> Und für Threads:
>> 1. Die postingmäßig größten Threadbäume
>> 2. Die Personen und in wie vielen Threadbäumen sie sind
>> 3. Die neuen Threads
>
> Das Problem dabei sind AFAICS z.B kaputte References, die leider keine
> Seltenheit sind. Das Problem zeigt sich gerade im laufenden Monat in
> dcs4-d im Thread "[Scripting] Neue Funktionen". Jedenfalls macht Dich
> Artikel <news:dcs4.05050...@gwaihir.akallabeth.de> zu einem
> Threadgründer.

Kaputte References sind tatsächlich ein Problem. Deshalb ziehe ich nur
die jeweils letzte Referenz zu Rate. Man kann davon ausgehen, dass
Newsreader wenigstens diese richtig behalten, wenn sie schon die
References als Kette kaputten. Zwar dürfen Newsreader die References
kürzen, sofern sie dabei aber wenigstens die erste und die beiden
letzten References behalten, was der Forte Agent, den der Poster des
oben genannten Artikels benutzt, aber offensichtlich nicht macht. Ich
nehme an, Du ziehst die gesamte Kette im Reference-Header zu Rate? Das
macht die Programmierung vom Thread-Auswertungen zwar erheblich
leichter, ist allerdings auch viel mehr von kaputteten References in
Mitleidenschaft zu ziehen.

>> 4. Die Ersteller der neuen Threads
>
> ... wie oben. :-/

Also wenn Du nach der ersten im References-Header genannten Referenz
gehst, dann hast Du in der Dialog-Gruppe noch Glück. Wo der Anteil an
erste References fressenden Newsreader höher ist, da schauts dann
schlechter aus.

>> 5. Die längsten Teilthreads mit einigen Daten
>
> Erfasst Du auch Subjektwechsel?

Nein, es war ja meine Intention, eben nicht nach den Subjects zu gehen.
Ich lasse bei den Teilthreads nur zur Information das Subject des ersten
und des letzten Artikels anzeigen.

Ralf Schoenian

unread,
May 15, 2005, 9:16:29 AM5/15/05
to
Mirko Dziadzka schrieb:

Achtung vor time.strptime(). Diese Funktion steht nicht in der
Windowswelt zur Verfuegung. Zumindest nicht unter NT.

Ralf Schoenian

Message has been deleted

Ralf Wachinger

unread,
May 15, 2005, 1:17:29 PM5/15/05
to
Ralf Schoenian schrieb:

> Achtung vor time.strptime(). Diese Funktion steht nicht in der
> Windowswelt zur Verfuegung. Zumindest nicht unter NT.

Seit Python Version 2.3 funktioniert time.strptime() auch unter Windows.

Maik Prinz

unread,
May 15, 2005, 6:28:05 PM5/15/05
to
*Ralf Wachinger* schrieb am So, 15. Mai. 2005 um 0:17...
[...]

> Dein Ergebnis der schnellsten Antwort von 2:36 Minuten kann ich jetzt
> positiv bestätigen.

Super... :-)

>> ... nun wollen wir mal nicht übertreiben. ;-)
>> Enrico hat da allerdings seine speziellen Wünsche für die Jahres-Stats.
> Aha, welche sind das denn?

Nope, es war nicht nur die Jahres-Statistik sondern eher allgemein:

stärkste Stunde # daran arbeiten wir ja gerade
stärkste Nacht (02:00 - 05:00 Uhr) # das gehört IMO besser in AFN ;)
...und - Ältestes unbeantwortetes Initialposting

>> Das war nicht ganz das Gesuchte, brachte mich aber mit diversen
>> Anpassungen auf den richtigen Weg. Sorry, der Code ist IMO etwas
>> Overkill:
>> [Code]
> Ja, der ist tatsächlich etwas overkillend, aber was solls, Hauptsache,
> er funktioniert. Ich hoffe, dass die Timedeltas in Zukunft eine
> Strftime-Methode verpasst bekommen.

Ein kleiner Fehler war aber dennoch enthalten, da ich sekunden in einen
String umgewandelt habe und anschließend "if sekunden==0:" getestet habe.

>> Die späteste Antwort gab es nach 5 Tagen, 20:03:57 Stunden

Habe ich jetzt noch unterteilt in:
Die späteste 1. Antwort gab es nach 5 Tagen, 22:07:06 Stunden
Die späteste weitere Antwort gab es nach 8 Tagen, 09:36:11 Stunden
da es AFAICS auch interessant sein kann, welche Artikel nach langer Zeit
überhaupt noch beantwortet werden.

>> ... und entspricht genau meinen Vorstellungen.
> Gut. Mir wäre es zu lang, denn meine Stat produziert mehr Daten, die ich
> in Spalten organisiere, da müssen die Texte kürzer sein.

Nun gut, ich habe halt nur ein paar Daten als Einleitung zusammengefasst.
Ansonsten müsste ich wie Du in AFN die Stats auch über mehrere aufteilen.

>>> Also ich habe jetzt auswertungsmäßig drin:
>>> 1. Die durchschnittliche, die kürzteste, die längste Antwortzeit
>>
>> Da ich nur von Artikel zu Artikel vergleiche, ist die durchschnittliche
>> Zeit bei mir vorerst nicht drin. Das ist mir persönlich auch nicht ganz
>> so wichtig.
> Ich mache das mit einer temporären Zeitspannenliste, wo alle jeweiligen
> Zeitspannen gesammelt werden, dann kann man bequem die Werte per max(),
> min(), sum() / len() rausziehen.

... mal schauen, ob ich dazu auch mal irgend wann die Muße habe. ;-)

>>> 2. Die Negativantwortzeiten, falls jemand eine falsche Zeit benutzt
>>
>> Habe ich als Kontrollfunktion - aber bisher ohne Treffer. :)
> Gibt derzeit auch keine in Dcs4-d.

In der Jahresstat 2004 habe ich auch nur wenige gefunden.

[Stärkste Stunde(n)]


> Du meinst die Zahlen von Oliver Cromm?

dito. :-)

> Da habe ich auch schon drüber nachgedacht. Eine bessere Methode als Du
> habe ich auch nicht. Ausgangspunkt ist eine nach Sekundenzeit sortierte
> Liste der Artikel. Dürfte verständlich sein, musst Du halt nur auf Dein
> spezielles Programm umsetzen:

Bis *jetzt* bin ich mit Codeabschnitten immer ganz gut klargekommen,
aber...

> -------------------------- Code schnipp ------------------------------
> def MeisteArtikelInZeitraum(self, stream, kenntext, sekundenzeitraum):

...wie und was muß hier ~~~~~~~~~~~~ übergeben werden?

> # Ab der Zeit des 'anfangsartikel' meiste Artikel 'maxArtikel'.
> anfangsartikel = 0
> maxArtikel = 0
> newsdatenliste = sorted(self.newsdaten.itervalues(), key = lambda artikel: artikel.sekundenzeit)

und woher erhalte ich das ~~~~~~~~~~~~~~ und das ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

> for index1, artikel in enumerate(newsdatenliste):
> for index2 in xrange(index1 + 1, len(newsdatenliste)):
> if newsdatenliste[index2].sekundenzeit - artikel.sekundenzeit < sekundenzeitraum:
> if index2 - index1 + 1 > maxArtikel:
> maxArtikel = index2 - index1 + 1
> anfangsartikel = artikel
> else:
> break

das ist dann wieder soweit verständlich für mich.

> print >> stream, ""
> print >> stream, "Die meisten Artikel innerhalb %s:" % kenntext
> print >> stream, " %4d Artikel zwischen %s und %s" \
> % (maxArtikel, anfangsartikel.Zeitstring(),
> time.strftime("%c", time.localtime(anfangsartikel.sekundenzeit + sekundenzeitraum - 1)))
> print >> stream, ""

das ~~~~~~~~~~ kannte ich noch gar nicht.

ich möchte das Ergebnis eigentlich auch nicht unbedingt innerhalb der
Funktion ausgeben sondern lieber zusammen mit anderen Daten in einer
vorhanden Liste für die spätere Ausgabe sammeln.

> self.MeisteArtikelInZeitraum(stream, "1 Stunde", 3600)
> self.MeisteArtikelInZeitraum(stream, "24 Stunden", 3600 * 24)

deshalb würde der Aufruf bei mir eher so aussehen:

statsData['MaxHour']=MeisteArtikelInZeitraum(stream, "1 Stunde", 3600)

was bei mir wieder zu der Frage führt, was genau mit *stream* übergeben
werden muß? Entschuldige bitte meine Unwissenheit aber ich bleibe als
Newbie immer noch oft an solchen Kleinigkeiten hängen. :-/

> -------------------------- Code schnapp ------------------------------
> Für April kriege ich das gleiche Ergebnis wie oben, für 01. - 13 Mai:
> Die meisten Artikel innerhalb 1 Stunde:
> 19 Artikel zwischen 02.05.05 22:53:12 und 02.05.05 23:53:11
> Die meisten Artikel innerhalb 24 Stunden:
> 109 Artikel zwischen 01.05.05 23:53:13 und 02.05.05 23:53:12

Stark, ich hoffe da komme ich auch mal hin. ;-))

[Thread-Statistik]


>> Das Problem dabei sind AFAICS z.B kaputte References, die leider keine
>> Seltenheit sind. Das Problem zeigt sich gerade im laufenden Monat in
>> dcs4-d im Thread "[Scripting] Neue Funktionen". Jedenfalls macht Dich
>> Artikel <news:dcs4.05050...@gwaihir.akallabeth.de> zu einem
>> Threadgründer.
> Kaputte References sind tatsächlich ein Problem.

Wie sich jetzt herausstellte, ist Individual für den anscheinend kaputten
Thread mitverantwortlich. Jedenfalls fehlt zu diesem Thread der
Owner-Artikel, was verschiedene Folgeartikel als Thread-Owner dastehen
lässt.

> Du ziehst die gesamte Kette im Reference-Header zu Rate?

Eigentlich nicht. Das Problem lag ja dann wohl auch nicht bei mir. Aber
erst wenn irgend welche Probleme auftauchen, forscht man meistens nach
einer Lösung. AFAIS ja auch immer wieder mal was optimieren. ;-))

Ralf Wachinger

unread,
May 18, 2005, 12:43:40 PM5/18/05
to
Maik Prinz schrieb:

> Nope, es war nicht nur die Jahres-Statistik sondern eher allgemein:
>
> stärkste Stunde # daran arbeiten wir ja gerade
> stärkste Nacht (02:00 - 05:00 Uhr) # das gehört IMO besser in AFN ;)
> ...und - Ältestes unbeantwortetes Initialposting

Das erste haben wir ja nun beide geschafft. Ich habe nun die Hauptarbeit
abgeschlossen, da das, was ich wollte nun ausgewertet wird, so dass das
zweite (und ähnliches) vielleicht irgendwann implementiert wird. Das
dritte interessiert mich nicht wirklich. Einmal festgestellt wird es
immer so bleiben, denn wer beantwortet so etwas Vergessenes noch.

> Habe ich jetzt noch unterteilt in:
> Die späteste 1. Antwort gab es nach 5 Tagen, 22:07:06 Stunden
> Die späteste weitere Antwort gab es nach 8 Tagen, 09:36:11 Stunden
> da es AFAICS auch interessant sein kann, welche Artikel nach langer Zeit
> überhaupt noch beantwortet werden.

Dass es nur jeweils 1 Wert ermittelt wird, hat mir bei meinem Programm
auch nicht gepasst, darum werden jetzt auch da X Werte errechnet.

> Nun gut, ich habe halt nur ein paar Daten als Einleitung zusammengefasst.
> Ansonsten müsste ich wie Du in AFN die Stats auch über mehrere aufteilen.

Da fragt sich eh, was besser ist: Alle Tabellen in 1 Posting oder je
Tabelle 1 Posting. Ich habe mehrtabellige Stats lieber in 1 Posting,
andere sind da anderer Meinung. Der gesamte Output Deines Programms ist
ja schon ganz schön groß.

> In der Jahresstat 2004 habe ich auch nur wenige gefunden.

Da Negativzeiten ja nur selten auftreten, dürfte das allgemein nicht
unserer Problem sein.

>> -------------------------- Code schnipp ------------------------------
>> def MeisteArtikelInZeitraum(self, stream, kenntext, sekundenzeitraum):
> ...wie und was muß hier ~~~~~~~~~~~~ übergeben werden?

"Self" kannst Du vergessen, das ist, weil bei mir alles in
Klassen-Objekten organisiert ist.

>> # Ab der Zeit des 'anfangsartikel' meiste Artikel 'maxArtikel'.
>> anfangsartikel = 0
>> maxArtikel = 0
>> newsdatenliste = sorted(self.newsdaten.itervalues(), key = lambda artikel: artikel.sekundenzeit)
> und woher erhalte ich das ~~~~~~~~~~~~~~ und das ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Für ersteres musst Du Deine eigene Datenstruktur nehmen. Zweiteres ist
so, weil bei mir die Artikel als Klassen-Objekte angelegt sind.

>> for index1, artikel in enumerate(newsdatenliste):
>> for index2 in xrange(index1 + 1, len(newsdatenliste)):
>> if newsdatenliste[index2].sekundenzeit - artikel.sekundenzeit < sekundenzeitraum:
>> if index2 - index1 + 1 > maxArtikel:
>> maxArtikel = index2 - index1 + 1
>> anfangsartikel = artikel
>> else:
>> break
>
> das ist dann wieder soweit verständlich für mich.

Dann OK.

>> print >> stream, ""
>> print >> stream, "Die meisten Artikel innerhalb %s:" % kenntext
>> print >> stream, " %4d Artikel zwischen %s und %s" \
>> % (maxArtikel, anfangsartikel.Zeitstring(),
>> time.strftime("%c", time.localtime(anfangsartikel.sekundenzeit + sekundenzeitraum - 1)))
>> print >> stream, ""
> das ~~~~~~~~~~ kannte ich noch gar nicht.

Der Parameter hinter "print >>" kann eine geöffnete Datei oder ein
ähnliches Objekt wie die Konsole (sys.stdout, ist immer geöffnet) sein:

def Ausgabe(stream, text):
print >> stream, text

datei = open("Beispiel.txt", "w")
Ausgabe(datei, "Hello World!")
datei.close()

schreibt in die Datei,

Ausgabe(sys.stdout, "Hello World!")

schreibt auf die Konsole (ist immer geöffnet). Somit braucht man für
Datei- und Konsolen-Ausgabe (und was sonst noch denkbar ist) keinen
getrennten Code.

> ich möchte das Ergebnis eigentlich auch nicht unbedingt innerhalb der
> Funktion ausgeben sondern lieber zusammen mit anderen Daten in einer
> vorhanden Liste für die spätere Ausgabe sammeln.

Verständlich. Verarbeitung und Ausgabe sollten eh besser getrennt
werden.

>> self.MeisteArtikelInZeitraum(stream, "1 Stunde", 3600)
>> self.MeisteArtikelInZeitraum(stream, "24 Stunden", 3600 * 24)
>
> deshalb würde der Aufruf bei mir eher so aussehen:
>
> statsData['MaxHour']=MeisteArtikelInZeitraum(stream, "1 Stunde", 3600)
>
> was bei mir wieder zu der Frage führt, was genau mit *stream* übergeben
> werden muß? Entschuldige bitte meine Unwissenheit aber ich bleibe als
> Newbie immer noch oft an solchen Kleinigkeiten hängen. :-/

Macht doch nichts. "Stream" kannst Du Dir auch sparen, wenn Du in der
Funktion nichts ausgibst.

>> -------------------------- Code schnapp ------------------------------
>> Für April kriege ich das gleiche Ergebnis wie oben, für 01. - 13 Mai:
>> Die meisten Artikel innerhalb 1 Stunde:
>> 19 Artikel zwischen 02.05.05 22:53:12 und 02.05.05 23:53:11
>> Die meisten Artikel innerhalb 24 Stunden:
>> 109 Artikel zwischen 01.05.05 23:53:13 und 02.05.05 23:53:12
>
> Stark, ich hoffe da komme ich auch mal hin. ;-))

Da bist Du doch jetzt, wie ich in Dcs4-d gesehen habe.

> Wie sich jetzt herausstellte, ist Individual für den anscheinend kaputten
> Thread mitverantwortlich. Jedenfalls fehlt zu diesem Thread der
> Owner-Artikel, was verschiedene Folgeartikel als Thread-Owner dastehen
> lässt.

Das ist nicht gut. Ich lade ja nicht mehr über Individual-Server,
sondern über den Arcor-Server.

>> Du ziehst die gesamte Kette im Reference-Header zu Rate?
>
> Eigentlich nicht. Das Problem lag ja dann wohl auch nicht bei mir. Aber
> erst wenn irgend welche Probleme auftauchen, forscht man meistens nach
> einer Lösung. AFAIS ja auch immer wieder mal was optimieren. ;-))

Das eh. Ich schaue manchmal alten Code von mir an und frage mich, wie
ich so umständlich programmieren konnte. Das liegt allerdings auch
daran, dass in Python ja immer neue Sprachelemente dazukommen, die die
Lösung von Coding-Problemen erleichtern.

Maik Prinz

unread,
May 18, 2005, 5:29:37 PM5/18/05
to
*Ralf Wachinger* schrieb am Mi, 18. Mai. 2005 um 18:43...

> Maik Prinz schrieb:
>> Nope, es war nicht nur die Jahres-Statistik sondern eher allgemein:
>>
>> stärkste Stunde # daran arbeiten wir ja gerade
>> stärkste Nacht (02:00 - 05:00 Uhr) # das gehört IMO besser in AFN ;)
>> ...und - Ältestes unbeantwortetes Initialposting
> Das erste haben wir ja nun beide geschafft.

Insbesondere Du, da ich ohne deine Unterstützung in der Time-Stat kaum
weitergekommen wäre. Außerdem fehlt bei mir gerade *das erste* noch.

[...]


> Das dritte interessiert mich nicht wirklich. Einmal festgestellt wird
> es immer so bleiben, denn wer beantwortet so etwas Vergessenes noch.

Na ja, langfristig gesehen magst Du ja recht haben, aber für die monatliche
Stat mußte ich jetzt feststellen, dass es doch ganz interessant sein kann.
Macht man z.B die Stats für den Januar, hat man eventuell ein
unbeantwortetes Initial-Posting am 8.01. welches in der Jahres-Stats dann
keine Rolle mehr spielt, weil es im Februar oder März doch noch beantwortet
wurde.

>> Nun gut, ich habe halt nur ein paar Daten als Einleitung zusammengefasst.
>> Ansonsten müsste ich wie Du in AFN die Stats auch über mehrere aufteilen.
> Da fragt sich eh, was besser ist: Alle Tabellen in 1 Posting oder je
> Tabelle 1 Posting. Ich habe mehrtabellige Stats lieber in 1 Posting,
> andere sind da anderer Meinung. Der gesamte Output Deines Programms ist
> ja schon ganz schön groß.

Ich wollte es aber auch bei einem Posting mit ca. 350 Lines belassen.

>>> -------------------------- Code schnipp ------------------------------
>>> def MeisteArtikelInZeitraum(self, stream, kenntext, sekundenzeitraum):
>> ...wie und was muß hier ~~~~~~~~~~~~ übergeben werden?
> "Self" kannst Du vergessen, das ist, weil bei mir alles in
> Klassen-Objekten organisiert ist.

Schon klar, aber was muß ich außer "kenntext" und "sekundenzeitraum" noch an
MeisteArtikelInZeitraum() übergeben? Ist es eine einfache Liste mit den
Sekundenwerten aller Artikel die dann z.B. so:

{[1116098021.0, 1116260982.0, 1111308494.0, 1113123772.0, ... ]}

aufgebaut ist oder wird noch mehr benötigt?

[...]


>>> newsdatenliste = sorted(self.newsdaten.itervalues(), key = lambda artikel: artikel.sekundenzeit)
>> und woher erhalte ich das ~~~~~~~~~~~~~~ und das ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> Für ersteres musst Du Deine eigene Datenstruktur nehmen. Zweiteres ist
> so, weil bei mir die Artikel als Klassen-Objekte angelegt sind.

Da die Daten bei mir AFAIS schon sortiert sind, kann hier doch die
übergebene Liste(?) newsdatenliste zugeordnet werden, oder?

[--8<--Code-geschnippt-->8--]


>> das ist dann wieder soweit verständlich für mich.
> Dann OK.

Wirklich verständlich für mich wird es dann aber erst, wenn ich die obige
Datenstruktur begriffen hane. %-/
Deshalb hoffe ich ja, dass Du mir das ganze an einem Beispiel, welches ich
vielleicht auch in der Console durchspielen kann, verständlich machen
kannst. :-)

>>> print >> stream, ""
>>> print >> stream, "Die meisten Artikel innerhalb %s:" % kenntext
>>> print >> stream, " %4d Artikel zwischen %s und %s" \
>>> % (maxArtikel, anfangsartikel.Zeitstring(),
>>> time.strftime("%c", time.localtime(anfangsartikel.sekundenzeit + sekundenzeitraum - 1)))
>>> print >> stream, ""
>> das ~~~~~~~~~~ kannte ich noch gar nicht.
> Der Parameter hinter "print >>" kann eine geöffnete Datei oder ein
> ähnliches Objekt wie die Konsole (sys.stdout, ist immer geöffnet) sein:
> def Ausgabe(stream, text):
> print >> stream, text
> datei = open("Beispiel.txt", "w")
> Ausgabe(datei, "Hello World!")
> datei.close()
> schreibt in die Datei,
> Ausgabe(sys.stdout, "Hello World!")
> schreibt auf die Konsole (ist immer geöffnet). Somit braucht man für
> Datei- und Konsolen-Ausgabe (und was sonst noch denkbar ist) keinen
> getrennten Code.

Das ist ja Klasse - hier lösen wir ganz nebenbei noch eine weitere meiner
vielen Fragen, die ich eigentlich erst in einem späteren Thread anbringen
wollte.
Ich weiß jetzt nur noch nicht, wie ich das in meinem Skript umsetze, da
gegenwärtig mehrere Print-Ausgaben über das Skript verstreut sind. Mit:

def Ausgabe(stream, text):
print >> stream, text

print text

datei = open("Beispiel.txt", "a")

Ausgabe(datei, "Hello World!")
datei.close()

wäre z.B. möglich parallel zur Ausgabe in der Console auch gleich eine Datei
zu mit den Daten zu füllen. Da ich die einzelnen Ausgabebereiche auch
unmittelbar in der Console sehen möchte, und nicht erst nach Abschluss aller
Aktionen, wäre das wohl die beste Alternative. Oder könnte man parallel zu
"print" die Daten auch für ein abschließendes beschreiben einer Datei
sammeln?

>> statsData['MaxHour']=MeisteArtikelInZeitraum(stream, "1 Stunde", 3600)
>>
>> was bei mir wieder zu der Frage führt, was genau mit *stream* übergeben
>> werden muß? Entschuldige bitte meine Unwissenheit aber ich bleibe als
>> Newbie immer noch oft an solchen Kleinigkeiten hängen. :-/
> Macht doch nichts. "Stream" kannst Du Dir auch sparen, wenn Du in der
> Funktion nichts ausgibst.

Da sind wir wieder bei obigen Problem, dass hier dann AFAIS nichts übergeben
wird - anstelle von Stream muss doch irgendwas zur Funktion ...?

>>> Die meisten Artikel innerhalb 1 Stunde:
>>> 19 Artikel zwischen 02.05.05 22:53:12 und 02.05.05 23:53:11
>>> Die meisten Artikel innerhalb 24 Stunden:
>>> 109 Artikel zwischen 01.05.05 23:53:13 und 02.05.05 23:53:12
>> Stark, ich hoffe da komme ich auch mal hin. ;-))
> Da bist Du doch jetzt, wie ich in Dcs4-d gesehen habe.

Nope, (noch)nichts dergleichen konnte ich bisher erfassen. :-(

Ralf Wachinger

unread,
May 19, 2005, 9:26:38 AM5/19/05
to
Maik Prinz schrieb:

> Insbesondere Du, da ich ohne deine Unterstützung in der Time-Stat kaum
> weitergekommen wäre. Außerdem fehlt bei mir gerade *das erste* noch.

Meinst Du mit "stärkste Stunde" hier eine Uhrzeit oder einen Zeitraum
wie unten besprochen?

> Na ja, langfristig gesehen magst Du ja recht haben, aber für die monatliche
> Stat mußte ich jetzt feststellen, dass es doch ganz interessant sein kann.
> Macht man z.B die Stats für den Januar, hat man eventuell ein
> unbeantwortetes Initial-Posting am 8.01. welches in der Jahres-Stats dann
> keine Rolle mehr spielt, weil es im Februar oder März doch noch beantwortet
> wurde.

So gesehen hat das mit den unbeantworteten Initialpostings mehr Sinn.
Bei meiner Stat sind das eine Untermenge in der Tabelle der neuen
Threads.

> Ich wollte es aber auch bei einem Posting mit ca. 350 Lines belassen.

Das sind schon ganz schön viele.

> Schon klar, aber was muß ich außer "kenntext" und "sekundenzeitraum" noch an
> MeisteArtikelInZeitraum() übergeben? Ist es eine einfache Liste mit den
> Sekundenwerten aller Artikel die dann z.B. so:
>
> {[1116098021.0, 1116260982.0, 1111308494.0, 1113123772.0, ... ]}
>
> aufgebaut ist oder wird noch mehr benötigt?

Nein. In der Funktion reicht eine sortierte Liste der Sekundenzeiten.

> Da die Daten bei mir AFAIS schon sortiert sind, kann hier doch die
> übergebene Liste(?) newsdatenliste zugeordnet werden, oder?

So ist es, als Parameter der Funktion. Siehe unten.

> Wirklich verständlich für mich wird es dann aber erst, wenn ich die obige
> Datenstruktur begriffen hane. %-/
> Deshalb hoffe ich ja, dass Du mir das ganze an einem Beispiel, welches ich
> vielleicht auch in der Console durchspielen kann, verständlich machen
> kannst. :-)

Es ist nicht leicht zu transferieren, weil mein Code objektorientiert
formuliert ist und Deiner klassisch strukturiert, zudem kenne ich Deine
Datenstrukturen nicht, jedoch siehe unten.

Übrigens: Zum Durchspielen eignet sich die Idle-Python-Shell am besten,
falls Du damit noch nicht gearbeitet hast. Dort kannst Du auch den Code
unten einfach ins interaktive Fenster zum Ausprobieren reinkopieren
(immer nur 1 Funktion auf einmal und dann ENTER drücken). Außerdem
kannst Du von dort Deine Scripte laden und ausführen lassen.

> Das ist ja Klasse - hier lösen wir ganz nebenbei noch eine weitere meiner
> vielen Fragen, die ich eigentlich erst in einem späteren Thread anbringen
> wollte.
> Ich weiß jetzt nur noch nicht, wie ich das in meinem Skript umsetze, da
> gegenwärtig mehrere Print-Ausgaben über das Skript verstreut sind. Mit:
>
> def Ausgabe(stream, text):
> print >> stream, text
> print text
>
> datei = open("Beispiel.txt", "a")
>
> Ausgabe(datei, "Hello World!")
> datei.close()
>
> wäre z.B. möglich parallel zur Ausgabe in der Console auch gleich eine Datei
> zu mit den Daten zu füllen. Da ich die einzelnen Ausgabebereiche auch
> unmittelbar in der Console sehen möchte, und nicht erst nach Abschluss aller
> Aktionen, wäre das wohl die beste Alternative. Oder könnte man parallel zu
> "print" die Daten auch für ein abschließendes beschreiben einer Datei
> sammeln?

Das geht auch. Auf jeden Fall müsstest Du alle print-Anweisungen durch
die Ausgabe-Funktion ersetzen. Dabei ist die besondere Syntax der print-
Anweisung zu beachten (kommagetrennte Werte mit Leerzeichen verkettet,
Zeilenschaltung am Ende, außer wenn Komma am Ende der Anweisung) und den
Parameter-Text dementsprechend verändern. Damit die Ausgabe dann
wirklich flexibel und nachträglich leicht auf die Ausgabeziele bezogen
veränderbar ist, würde ich eine Klasse formulieren, die die Ausgaben
managet. Ist zwar mehr Aufwand, aber auf längere Sicht lohnt sie sich.
Inwieweit kennst Du Dich mit objektorientierter Programmierung aus (ohne
die kann man Python eh nicht vollständig und elegant nutzen)?

> Da sind wir wieder bei obigen Problem, dass hier dann AFAIS nichts übergeben
> wird - anstelle von Stream muss doch irgendwas zur Funktion ...?

Ja, die Liste der Sekundenzeiten. Ich formuliere den Code mal neu, davon
ausgehend, dass "newsdatenliste" eine schon sortierte Liste mit den
Sekundenzeiten aller Artikel ist:

--------------------------- Code schnipp -----------------------------

def Lokalzeit(sekundenzeit):
"Gibt die Sekundenzeit als String in lokaler Zeit zurück"

return time.strftime("%d.%m.%Y %H:%M:%S", time.localtime(sekundenzeit))


def MeisteArtikelInZeitraum(newsdatenliste, kenntext, sekundenzeitraum):


"Berechnet, wann innerhalb eines Zeitraums die meisten Artikel gepostet wurden"

# Ab der Zeit des 'anfangsartikel' meiste Artikel 'maxArtikel'.
anfangszeit = 0
maxArtikel = 0

for index1, sekundenzeit in enumerate(newsdatenliste):


for index2 in xrange(index1 + 1, len(newsdatenliste)):

if newsdatenliste[index2] - sekundenzeit < sekundenzeitraum:


if index2 - index1 + 1 > maxArtikel:
maxArtikel = index2 - index1 + 1

anfangszeit = sekundenzeit
else:
break

return "\nDie meisten Artikel innerhalb %s:" % kenntext + \
"\n %4d Artikel zwischen %s und %s\n" \
% (maxArtikel, Lokalzeit(anfangszeit),
Lokalzeit(anfangszeit + sekundenzeitraum - 1))


statsData['MaxHour'] = MeisteArtikelInZeitraum(newsdatenliste, "1 Stunde", 3600)

--------------------------- Code schnapp -----------------------------

Die Funktion Lokalzeit() wirst Du öfters brauchen, wenn Du mit
Sekundenzeiten arbeitest. Die Mktime_tz- + Parsedate_tz-Funktion aus
email.Utils gibt nämlich die Sekundenzeit in GMT zurück, weil
logischerweise nur eine bestimmte Anzahl von Sekunden seit dem
01.01.1970 vergangen sein kann. Den Aufruf der Funktion habe ich nach
dem von Dir angegebenen Codemuster gestaltet.

Übrigens: Ich benutze in meinem Programm das Modul Datetime nicht, darum
läuft die Berechnung allgemein über Sekundenzeiten als Basis, die mit
den Funktionen aus dem Time-Modul in Strings umgewandelt werden, zumal
die email.Utils-Fuktionen Sekundenzeiten zurückgeben. Die andere
Möglichkeit wäre, Timedelta- und Datetime-Objekte aus dem Datetime-Modul
zu benutzen. Die Vermischung von beiden Sachen gibt irgendwann ein
Durcheinander (es *herrscht* ein Durcheinander in Python zwischen alt
und neu). Ich hatte Dir zu Timedelta-Objekten geraten, weil ich meinte,
Du willst für die Zeiten Datetime-Objekte benutzen.

>> Da bist Du doch jetzt, wie ich in Dcs4-d gesehen habe.
>
> Nope, (noch)nichts dergleichen konnte ich bisher erfassen. :-(

Dann habe ich es falsch gesehen.

Maik Prinz

unread,
May 19, 2005, 12:09:52 PM5/19/05
to
* am Do, 19. Mai. 2005 um 15:26 war von Ralf Wachinger zu lesen...

>> Insbesondere Du, da ich ohne deine Unterstützung in der Time-Stat kaum
>> weitergekommen wäre. Außerdem fehlt bei mir gerade *das erste* noch.
> Meinst Du mit "stärkste Stunde" hier eine Uhrzeit oder einen Zeitraum
> wie unten besprochen?

... die stärkste Stunde bzw. 24h in einem bestimmten Zeitraum.

>> Ich wollte es aber auch bei einem Posting mit ca. 350 Lines belassen.
> Das sind schon ganz schön viele.

Schon, aber immer noch keine 1,2k Lines wie wir sie in dcs4-d schon
gesehen haben. :-) Wir belegen in diesem Tread mit den Lines aber
bestimmt auch einen Spitzenplatz[tm].

[...]


>> Deshalb hoffe ich ja, dass Du mir das ganze an einem Beispiel, welches ich
>> vielleicht auch in der Console durchspielen kann, verständlich machen
>> kannst. :-)

[...]


> Übrigens: Zum Durchspielen eignet sich die Idle-Python-Shell am besten,
> falls Du damit noch nicht gearbeitet hast.

Na klar doch s/Console/Idle-Python-Shell/ :-)

[...]


>> datei = open("Beispiel.txt", "a")

[...]


>> wäre z.B. möglich parallel zur Ausgabe in der Console auch gleich eine Datei
>> zu mit den Daten zu füllen. Da ich die einzelnen Ausgabebereiche auch
>> unmittelbar in der Console sehen möchte, und nicht erst nach Abschluss aller
>> Aktionen, wäre das wohl die beste Alternative. Oder könnte man parallel zu
>> "print" die Daten auch für ein abschließendes beschreiben einer Datei
>> sammeln?
> Das geht auch. Auf jeden Fall müsstest Du alle print-Anweisungen durch
> die Ausgabe-Funktion ersetzen. Dabei ist die besondere Syntax der print-
> Anweisung zu beachten (kommagetrennte Werte mit Leerzeichen verkettet,
> Zeilenschaltung am Ende, außer wenn Komma am Ende der Anweisung) und den
> Parameter-Text dementsprechend verändern.

Ich werde mal ein wenig experimentieren und bestimmt was geeignetes
daraus mache. Ist es eigentlich auch möglich, open() den gesamten Pfad
mitzugeben, und das eventuell sogar dann, wenn ein Unterordner bis dahin
noch gar nicht existiert?

> Damit die Ausgabe dann wirklich flexibel und nachträglich leicht auf
> die Ausgabeziele bezogen veränderbar ist, würde ich eine Klasse
> formulieren, die die Ausgaben managet. Ist zwar mehr Aufwand, aber
> auf längere Sicht lohnt sie sich.

Oh man, mit den Begriffen tue ich mich im Moment noch schwer. Mit mehr
Aufwand meinst Du, dass zunächst etwas entwickelt/programmiert werden
müsste, was dann aber später flexibel wiederverwendet werden kann?

> Inwieweit kennst Du Dich mit objektorientierter Programmierung aus (ohne
> die kann man Python eh nicht vollständig und elegant nutzen)?

Frage besser nicht ;) - wie zuvor habe ich damit bestimmt schon zutun
gehabt, ohne das ich mir dessen bewußt war.

>> Da sind wir wieder bei obigen Problem, dass hier dann AFAIS nichts übergeben
>> wird - anstelle von Stream muss doch irgendwas zur Funktion ...?
> Ja, die Liste der Sekundenzeiten. Ich formuliere den Code mal neu, davon
> ausgehend, dass "newsdatenliste" eine schon sortierte Liste mit den
> Sekundenzeiten aller Artikel ist:

Das Sortieren ist ja mit newsdatenliste.sort() das geringste Problem. ;)
Ich habe den Code nicht nochmal Zitiert, kann aber mit Freude berichten,
dass es so auch in meiner Code-Wüßte[tm] seine Aufgabe erfüllt. :-))

> Die Funktion Lokalzeit() wirst Du öfters brauchen, wenn Du mit
> Sekundenzeiten arbeitest. Die Mktime_tz- + Parsedate_tz-Funktion aus
> email.Utils gibt nämlich die Sekundenzeit in GMT zurück, weil
> logischerweise nur eine bestimmte Anzahl von Sekunden seit dem
> 01.01.1970 vergangen sein kann.

Das sind dann wieder die schon mehrmals besprochenen Optimierungen,
indem man wiederkehrendes einfach in eine Funktion packt. :)

> Übrigens: Ich benutze in meinem Programm das Modul Datetime nicht, darum
> läuft die Berechnung allgemein über Sekundenzeiten als Basis, die mit
> den Funktionen aus dem Time-Modul in Strings umgewandelt werden, zumal
> die email.Utils-Fuktionen Sekundenzeiten zurückgeben.

Kannst Du mal mit Deinem Skript schauen, wieviele Artikel Oliver im März
und April jeweils in dcs4-d hatte. Momentan arbeitet das Skript bei mir
wohl noch nicht korrekt bei Artikeln aus anderen Zeitzonen, was ich dann
aber mit dem Time-Modul sicherlich elegant lösen könnte. Wenn ich dann
z.B. aus dem Sekundenwert mit Sekundenwert.strftime("%m") den Monat
zurückhole, müßte dieser doch dann einheitlich unserer Localtime
zugeordnet sein!?

>>> Da bist Du doch jetzt, wie ich in Dcs4-d gesehen habe.
>> Nope, (noch)nichts dergleichen konnte ich bisher erfassen. :-(
> Dann habe ich es falsch gesehen.

Macht ja nicht, jetzt klappt es jedenfalls Dank Deiner Hilfe. :-)


THX, Maik
--
250+ 3D Wallpaper: http://www.2prinz.de

40tude Dialog - Free Windows-Newsreader
Download: http://www.40tude.com/dialog/

Maik Prinz

unread,
May 19, 2005, 12:27:51 PM5/19/05
to
* am Do, 19. Mai. 2005 um 18:09 war von Ingrid zu lesen...

> Kannst Du mal mit Deinem Skript schauen, wieviele Artikel Oliver im März
> und April jeweils in dcs4-d hatte. Momentan arbeitet das Skript bei mir
> wohl noch nicht korrekt bei Artikeln aus anderen Zeitzonen, was ich dann
> aber mit dem Time-Modul sicherlich elegant lösen könnte. Wenn ich dann
> z.B. aus dem Sekundenwert mit Sekundenwert.strftime("%m") den Monat
> zurückhole, müßte dieser doch dann einheitlich unserer Localtime
> zugeordnet sein!?

Ich habe das ganze mal durchgespielt, und komme zu folgendem Ergebnis:

,----
| >>> Sekundenwert = email.Utils.mktime_tz(email.Utils.parsedate_tz('Thu, 31 Mar 2005 23:40:06 -0500'))
| >>> print int(time.strftime("%m", time.localtime(Sekundenwert)))
| 4
`----

... so das ich wohl diesbezüglich umbauen muss. Bisher fehlten nämlich
diese Artikel immer in den Stats des Folgemonats, was sich damit wohl
vermeiden lässt.


cu, Maik

Ralf Wachinger

unread,
May 20, 2005, 5:01:35 AM5/20/05
to
Maik Prinz schrieb:

>> Meinst Du mit "stärkste Stunde" hier eine Uhrzeit oder einen Zeitraum
>> wie unten besprochen?
>
> ... die stärkste Stunde bzw. 24h in einem bestimmten Zeitraum.

Diesen Wert lasse ich noch nicht extra errechnen.

> Schon, aber immer noch keine 1,2k Lines wie wir sie in dcs4-d schon
> gesehen haben. :-) Wir belegen in diesem Tread mit den Lines aber
> bestimmt auch einen Spitzenplatz[tm].

Durchaus, und im Mai sowieso. Viel ist ja noch nicht in dieser Gruppe
los. Es tummeln sich ja viele in Mailinglisten und Foren mit Thema
Python.

> Ich werde mal ein wenig experimentieren und bestimmt was geeignetes
> daraus mache. Ist es eigentlich auch möglich, open() den gesamten Pfad
> mitzugeben, und das eventuell sogar dann, wenn ein Unterordner bis dahin
> noch gar nicht existiert?

Pfade angeben kann man in open() natürlich auch. Du musst nur aufpassen
wegen der Backslashes. Entweder escapst Du sie, ironischerweise mit
Backslash: "C:\\Programme\\Beispiel.txt" oder besser Du benutzt
Raw-Strings, mit einem kleinen r vorne: r"C:\Programme\Beispiel.txt".
Raw-Strings oder es sind sogar normale Slashes erlaubt:
"C:/Programme/Beispiel.txt".

Einen Unterordner musst Du erst vorher anlegen:
import os
os.mkdir(r"D:\Ordner\Unterordner")

> Oh man, mit den Begriffen tue ich mich im Moment noch schwer. Mit mehr
> Aufwand meinst Du, dass zunächst etwas entwickelt/programmiert werden
> müsste, was dann aber später flexibel wiederverwendet werden kann?

Ja, so in etwa. Aber entwickeln musst Du eh. Und *einmal* ein bisschen
mehr Arbeit in eine Klasse stecken und diese dann *mehrfach einfach*
benutzen, ist insgesamt weniger Arbeit, als mit einer einzelnen Funktion
*einmal* weniger Arbeit haben und dann *nachfolgend* wahrscheinlich
*mehr*.

>> Inwieweit kennst Du Dich mit objektorientierter Programmierung aus (ohne
>> die kann man Python eh nicht vollständig und elegant nutzen)?
>
> Frage besser nicht ;) - wie zuvor habe ich damit bestimmt schon zutun
> gehabt, ohne das ich mir dessen bewußt war.

Klar, z. B. sind Datetime- und Timedelta-Objekte Instanzen von
OOP-Klassen oder jeder String ist eine Instanz der Klasse str. Ohne OOP
programmieren in Python, ich will es mal so ausdrücken: Jemand hat einen
Trabi und einen Porsche in der Garage, benutzt aber nur den Trabi, weil
ihm der Porsche zu schnell ist ;o)

> Das Sortieren ist ja mit newsdatenliste.sort() das geringste Problem. ;)
> Ich habe den Code nicht nochmal Zitiert, kann aber mit Freude berichten,
> dass es so auch in meiner Code-Wüßte[tm] seine Aufgabe erfüllt. :-))

Dann passt es ja.

> Das sind dann wieder die schon mehrmals besprochenen Optimierungen,
> indem man wiederkehrendes einfach in eine Funktion packt. :)

Das sind nicht nur Optimierungen, sondern Grundlagen der strukturierten
und besonders der OOP-Programmierung, die man leider immer wieder mal
nicht durchgehend anwendet.

> Kannst Du mal mit Deinem Skript schauen, wieviele Artikel Oliver im März
> und April jeweils in dcs4-d hatte. Momentan arbeitet das Skript bei mir
> wohl noch nicht korrekt bei Artikeln aus anderen Zeitzonen, was ich dann
> aber mit dem Time-Modul sicherlich elegant lösen könnte. Wenn ich dann
> z.B. aus dem Sekundenwert mit Sekundenwert.strftime("%m") den Monat
> zurückhole, müßte dieser doch dann einheitlich unserer Localtime
> zugeordnet sein!?

Es ist wirklich zum Haareraufen mit den Python Zeitfunktionen. Man muss
immer darauf achten, ob sie GMT oder lokale Zeit zurückgeben. Und die
verschiedenen Systeme mit Sekundenzeiten, Time-Tupeln, Date-Headern,
Datumsstrings tragen auch nicht gerade zur Erhellung bei.

| ,----
|| >>> Sekundenwert = email.Utils.mktime_tz(email.Utils.parsedate_tz('Thu, 31 Mar 2005 23:40:06 -0500'))
|| >>> print int(time.strftime("%m", time.localtime(Sekundenwert)))
|| 4
| `----
|
| ... so das ich wohl diesbezüglich umbauen muss. Bisher fehlten nämlich
| diese Artikel immer in den Stats des Folgemonats, was sich damit wohl
| vermeiden lässt.

Die 2 von Dir zitierten Zeilen sind in sich stimmig, denn die
Date-Header-Zeit oben ist nach mitteleuropäischer Sommerzeit schon
April. Wenn Du den auszuwertenden Zeitraum als Teilstring-Suche im
Date-Header vornimmst, dann musst Du alle Date-Header auf 1 Basis
bringen, also MEZ/MES, dafür gibt es die Funktion
email.Utils.formatdate(). Die Sekundenzeit, mit der Du rechnest, ist
zwar in GMT, aber Du musst zum Zugriff auf bestimmte Zeiteinheiten oder
zur Ausgabe eh die Funktion time.localtime() anwenden:

dateheader = 'Thu, 31 Mar 2005 23:40:06 -0500'
zeit = email.Utils.mktime_tz(email.Utils.parsedate_tz(dateheader))
dateheader = email.Utils.formatdate(zeit, localtime = True)

dateheader
--> 'Fri, 01 Apr 2005 06:40:06 +0200'

monatJahr in dateheader
--> True

time.localtime(zeit).tm_hour
--> 6

time.localtime(zeit).tm_mday
--> 1

time.strftime("%d.%m.%Y %H:%M:%S", time.localtime(zeit))
--> '01.04.2005 06:40:06'

Eine andere Möglichkeit ist, Datetime-Objekte zu benutzen. Dies ziehe
ich inzwischen vor und formuliere mein Thread- und
Zeitspannen-Berechnungs-Modul dergestalt um, weil es die Dinge
vereinfacht. Es wird jeder Date-Header in ein Datetime-Objekt
umgewandelt, was einem das parallele Benötigen von angepassten
Date-Headern und Sekundenzeiten erspart und auch das Drandenken, ob man
gerade GMT oder lokale Zeit vor sich hat:

monat = 4; jahr = 2005
dateheader = 'Thu, 31 Mar 2005 23:40:06 -0500'
zeit = email.Utils.mktime_tz(email.Utils.parsedate_tz(dateheader))
datumzeit = datetime.datetime.fromtimestamp(zeit)

monat == datumzeit.month and jahr == datumzeit.year
--> True

datumzeit.hour
--> 6

datumzeit.day
--> 1

datumzeit.strftime("%d.%m.%Y %H:%M:%S")
--> '01.04.2005 06:40:06'

Maik Prinz

unread,
May 22, 2005, 12:35:02 PM5/22/05
to
*Ralf Wachinger* schrieb am Fr, 20. Mai. 2005 um 11:01...

>>> Meinst Du mit "stärkste Stunde" hier eine Uhrzeit oder einen Zeitraum
>>> wie unten besprochen?
>> ... die stärkste Stunde bzw. 24h in einem bestimmten Zeitraum.
> Diesen Wert lasse ich noch nicht extra errechnen.

Das habe ich jetzt soweit alles dank deiner Hilfe integrieren können.
Sogar die "stärkste Nacht (0-6Uhr)" habe ich jetzt drin. :-)

>> Schon, aber immer noch keine 1,2k Lines wie wir sie in dcs4-d schon
>> gesehen haben. :-) Wir belegen in diesem Tread mit den Lines aber
>> bestimmt auch einen Spitzenplatz[tm].
> Durchaus, und im Mai sowieso. Viel ist ja noch nicht in dieser Gruppe
> los.

Schade eigentlich - soll uns aber nicht davon abhalten. Im Gegenteil.

>> Ich werde mal ein wenig experimentieren und bestimmt was geeignetes
>> daraus mache. Ist es eigentlich auch möglich, open() den gesamten Pfad
>> mitzugeben, und das eventuell sogar dann, wenn ein Unterordner bis dahin
>> noch gar nicht existiert?
> Pfade angeben kann man in open() natürlich auch. Du musst nur aufpassen
> wegen der Backslashes. Entweder escapst Du sie, ironischerweise mit
> Backslash: "C:\\Programme\\Beispiel.txt" oder besser Du benutzt
> Raw-Strings, mit einem kleinen r vorne: r"C:\Programme\Beispiel.txt".

Wie lassen sich solche Raw-Strings bei zusammengesetzten Informationen
nutzen? Ich möchte z.B. in einem Konfigurationsskript den Wert "filepfad"
übergeben und den Dateinamen aus einer Kombination von Jahr, Monat und NG
erstellen (dateiname=r?+filepfad + dateiname). Kann der Pfad dann auch
Leerzeichen enthalten?

> Einen Unterordner musst Du erst vorher anlegen:

> os.mkdir(r"D:\Ordner\Unterordner")

Wenn der Ordner bereits vorhanden ist, wird er doch hoffentlich nicht
überschrieben. Besser wäre jedoch, wen man vorher auf den Ordner prüfen
könnte und nur bei nicht vorhanden sein einen neuen Ordner erstellt.

In meinem Skript habe ich die Ausgabe jetzt so gelöst:

def Ausgabe(dateiname, text, New=None):
dateiname=filepfad + dateiname
if New==1 and usefile: datei = open(dateiname, "w")
elif usefile: datei = open(dateiname, "a")
if usefile:
print >> datei, text
datei.close()
if useIDLE: print text

Per "usefile" bzw. "useIDLE" lässt sich so ganz bequem einstellen, wo die
Ausgabe stattfinden soll.

[Date-Header auf Localtime bringen]


> dateheader = 'Thu, 31 Mar 2005 23:40:06 -0500'
> zeit = email.Utils.mktime_tz(email.Utils.parsedate_tz(dateheader))
> dateheader = email.Utils.formatdate(zeit, localtime = True)
> dateheader
> --> 'Fri, 01 Apr 2005 06:40:06 +0200'

[...]

Das ist ja Super, nur zwei zusätzliche Zeilen und es scheint jetzt auch
bei mir im Vergleich zu Stat von Oliver alles zu stimmen. :-)

> Eine andere Möglichkeit ist, Datetime-Objekte zu benutzen. Dies ziehe
> ich inzwischen vor und formuliere mein Thread- und
> Zeitspannen-Berechnungs-Modul dergestalt um, weil es die Dinge
> vereinfacht. Es wird jeder Date-Header in ein Datetime-Objekt
> umgewandelt, was einem das parallele Benötigen von angepassten
> Date-Headern und Sekundenzeiten erspart und auch das Drandenken, ob man
> gerade GMT oder lokale Zeit vor sich hat:

Soweit bin ich zunächst nicht gegangen, weil mir bislang noch nicht die
gesamte Struktur des Skripts geläufig ist. Darauf werde ich aber bestimmt
zurückkommen - Dein Artikel habe ich auf jeden Fall erstmal in Dialog
archiviert. Vielen Dank auch nochmal für Deine Geduld mit mir. :-)

BTW: Erstellst Du die Statistiken ausschließlich über den Hamster und wie
greifst du auf die Daten zu? Vermutlich kannst Due auch den Supersedes im
Header auswerten, was AFAICS mit der nntp-lib nicht möglich ist. :-/


cu, Maik

Ralf Wachinger

unread,
May 23, 2005, 11:32:14 AM5/23/05
to
Maik Prinz schrieb:

> Das habe ich jetzt soweit alles dank deiner Hilfe integrieren können.
> Sogar die "stärkste Nacht (0-6Uhr)" habe ich jetzt drin. :-)

Mensch, jetzt muss ich das auch noch bei mir integrieren, damit ich Dir
in nichts nachstehe ;o)

>> Durchaus, und im Mai sowieso. Viel ist ja noch nicht in dieser Gruppe
>> los.
>
> Schade eigentlich - soll uns aber nicht davon abhalten. Im Gegenteil.

Eben. Wenn sich jeder denkt "Ach, da ist ja nichts los, also bringt es
nichts mitzumachen.", dann ist wirklich nichts los hier :o)

> Wie lassen sich solche Raw-Strings bei zusammengesetzten Informationen
> nutzen? Ich möchte z.B. in einem Konfigurationsskript den Wert "filepfad"
> übergeben und den Dateinamen aus einer Kombination von Jahr, Monat und NG
> erstellen (dateiname=r?+filepfad + dateiname). Kann der Pfad dann auch
> Leerzeichen enthalten?

Raw-Strings und gewöhnliche Strings lassen sich ganz normal verketten.
Pfade und Dateinamen können alle Zeichen enthalten, die auch das
Betriebssystem erlaubt.

> Wenn der Ordner bereits vorhanden ist, wird er doch hoffentlich nicht
> überschrieben. Besser wäre jedoch, wen man vorher auf den Ordner prüfen
> könnte und nur bei nicht vorhanden sein einen neuen Ordner erstellt.

Er wird nicht überschrieben, sondern es gibt wird eine Ausnahme
ausgeworfen. Auf Vorhandensein überprüft man mit os.path.exists(), wobei
man als Parameter sowohl einen Ordner als auch eine Datei angeben kann.

> In meinem Skript habe ich die Ausgabe jetzt so gelöst:
>
> def Ausgabe(dateiname, text, New=None):
> dateiname=filepfad + dateiname
> if New==1 and usefile: datei = open(dateiname, "w")
> elif usefile: datei = open(dateiname, "a")
> if usefile:
> print >> datei, text
> datei.close()
> if useIDLE: print text
>
> Per "usefile" bzw. "useIDLE" lässt sich so ganz bequem einstellen, wo die
> Ausgabe stattfinden soll.

Ja, das dürfte so funktionieren, allerdings ist es ein bisschen
ungewöhnlich, für jeden Schreibvorgang die Datei zu öffnen und wieder zu
schließen, statt öffnen vor dem ersten und schließen nach dem letzten
Schreibvorgang. Außerdem können beim Datei-Anlegen, -Öffnen oder
-Schreiben Fehler auftreten, deshalb solltest Du, sobald der vollständige
Dateiname feststeht und vor dem Newsdatenholen, die Datei testweise im
Modus "a" öffnen und wieder schließen, sonst hat Dein Programm umsonst
Daten geschaufelt, bevor es einen eventuellen Fehler bemerkt. Ansonsten
dürfte das Obige für Deine Zwecke wohl reichen.

Ich habe auch schon darüber nachgedacht, mein Programm dergestalt
flexibler zu machen und bin am Schreiben einer Ausgabeklasse für
allgemeine Verwendung.

> [Date-Header auf Localtime bringen]


> Das ist ja Super, nur zwei zusätzliche Zeilen und es scheint jetzt auch
> bei mir im Vergleich zu Stat von Oliver alles zu stimmen. :-)

Dann passt es ja. Ich habe damals in den Anfangszeiten meines Programms
alles in mühevoller Arbeit herausgefunden, aber auch dadurch lernt man.

>> [GMT oder lokale Zeit]

Du musst bloß in Erinnerung behalten, dass Dein Script nun in lokaler
Zeit - also bei uns mitteleuropäischer Zeit - arbeitet, während AgtFind
und GoldFind immer in GMT arbeiten, was theoretisch zwar richtig, für
die Praxis aber verwirrend ist. Mein Programm statistiziert in MEZ mit
Beachtung der Sommer- und Winterzeit.

> Soweit bin ich zunächst nicht gegangen, weil mir bislang noch nicht die
> gesamte Struktur des Skripts geläufig ist. Darauf werde ich aber bestimmt
> zurückkommen - Dein Artikel habe ich auf jeden Fall erstmal in Dialog
> archiviert. Vielen Dank auch nochmal für Deine Geduld mit mir. :-)

Dadurch, dass ich Dir weiterhelfe, kommt mir das eine oder andere in den
Sinn, das ich bei mir noch verbessern oder aufnehmen kann :-)

> BTW: Erstellst Du die Statistiken ausschließlich über den Hamster und wie
> greifst du auf die Daten zu? Vermutlich kannst Due auch den Supersedes im
> Header auswerten, was AFAICS mit der nntp-lib nicht möglich ist. :-/

Bei Gruppen, die ich im Hamster habe, hole ich mir die Artikel - und
zwar die ganzen - per OLE aus dem Hamster, das geht schneller als per
NNTP, hat jedoch vom Artikelzugriff her weniger Möglichkeiten als NNTP,
erlaubt jedoch eine Fernsteuerung des Hamsters über Python (benutze ich
jedoch nicht). Bestimmte Header kannst Du doch mit nntplib.xhdr()
holen. Soweit ich sehe, arbeitet Ngstat doch auch damit. Python gibt für
jeden Header, der nicht existiert den String "(none)" zurück, damit
kannst Du die nicht infrage kommenden Artikel ausfiltern.

Maik Prinz

unread,
May 23, 2005, 4:53:13 PM5/23/05
to
*Ralf Wachinger* schrieb am Mo, 23. Mai. 2005 um 17:32...

>> Das habe ich jetzt soweit alles dank deiner Hilfe integrieren können.
>> Sogar die "stärkste Nacht (0-6Uhr)" habe ich jetzt drin. :-)
> Mensch, jetzt muss ich das auch noch bei mir integrieren, damit ich Dir
> in nichts nachstehe ;o)

Oje, das sollte jetzt kein Aufruf zum Wettbewerb sein. Bei Deinen
AFN-Stats kann ich

| >> Ich wollte es aber auch bei einem Posting mit ca. 350 Lines belassen.
| > Das sind schon ganz schön viele.

BTW hat die Mozilla-Statistik (dcsm*) sogar 826 Lines. ;-/

>> Wie lassen sich solche Raw-Strings bei zusammengesetzten Informationen
>> nutzen? Ich möchte z.B. in einem Konfigurationsskript den Wert "filepfad"
>> übergeben und den Dateinamen aus einer Kombination von Jahr, Monat und NG
>> erstellen (dateiname=r?+filepfad + dateiname). Kann der Pfad dann auch
>> Leerzeichen enthalten?
> Raw-Strings und gewöhnliche Strings lassen sich ganz normal verketten.
> Pfade und Dateinamen können alle Zeichen enthalten, die auch das
> Betriebssystem erlaubt.

Das funktioniert jetzt soweit auch. Ich hatte zunächst ein
Verständnisproblem, wo das r zu setzen ist. Anscheinend kann dieses nur
direkt bei der Wertzuweisung z.B. filepfad=r'D:\Test' geschehen.

>> Wenn der Ordner bereits vorhanden ist, wird er doch hoffentlich nicht
>> überschrieben. Besser wäre jedoch, wen man vorher auf den Ordner prüfen
>> könnte und nur bei nicht vorhanden sein einen neuen Ordner erstellt.
> Er wird nicht überschrieben, sondern es gibt wird eine Ausnahme
> ausgeworfen. Auf Vorhandensein überprüft man mit os.path.exists(), wobei
> man als Parameter sowohl einen Ordner als auch eine Datei angeben kann.

Super, dann werde ich damit noch eine Sicherheitsabfrage einbauen und
ggf. den Ordner erstellen lassen.

>> def Ausgabe(dateiname, text, New=None):
>> dateiname=filepfad + dateiname
>> if New==1 and usefile: datei = open(dateiname, "w")
>> elif usefile: datei = open(dateiname, "a")
>> if usefile:
>> print >> datei, text
>> datei.close()
>> if useIDLE: print text

> Ja, das dürfte so funktionieren, allerdings ist es ein bisschen
> ungewöhnlich, für jeden Schreibvorgang die Datei zu öffnen und wieder zu
> schließen, statt öffnen vor dem ersten und schließen nach dem letzten
> Schreibvorgang.

So habe ich halt im Falle eines vorzeitigen Abbruchs dennoch Daten in
der Datei. So hat man auch bei fehlendem useIDLE immer ein Resultat.

> Außerdem können beim Datei-Anlegen, -Öffnen oder
> -Schreiben Fehler auftreten, deshalb solltest Du, sobald der vollständige
> Dateiname feststeht und vor dem Newsdatenholen, die Datei testweise im
> Modus "a" öffnen und wieder schließen, sonst hat Dein Programm umsonst
> Daten geschaufelt, bevor es einen eventuellen Fehler bemerkt.

Ich hole nicht bei jeder Statistikerstellung Daten sondern lade nur ggf.
neue dazu. Diese werden dann zusammen in eine Datei gespeichert von wo
aus das abarbeiten der Daten erfolgt.

> Ansonsten dürfte das Obige für Deine Zwecke wohl reichen.

Tut es ja auch, ohne das irgendwelche Performance-Last zu merken ist.

> Ich habe auch schon darüber nachgedacht, mein Programm dergestalt
> flexibler zu machen und bin am Schreiben einer Ausgabeklasse für
> allgemeine Verwendung.

Da geht es ja bei Dir um einiges weiter, da AFAIR sogar Stats für die
Nutzung auf Webseiten geschrieben werden sollen.

>>> [GMT oder lokale Zeit]
> Du musst bloß in Erinnerung behalten, dass Dein Script nun in lokaler
> Zeit - also bei uns mitteleuropäischer Zeit - arbeitet, während AgtFind
> und GoldFind immer in GMT arbeiten, was theoretisch zwar richtig, für
> die Praxis aber verwirrend ist. Mein Programm statistiziert in MEZ mit
> Beachtung der Sommer- und Winterzeit.

~~~~~~~~~~~~~~~~~~~~~~
Lokal-Zeit heißt doch, dass *dies* auch berücksichtigt wird, oder?

> Dadurch, dass ich Dir weiterhelfe, kommt mir das eine oder andere in den
> Sinn, das ich bei mir noch verbessern oder aufnehmen kann :-)

Keine Ursache, ich helfe doch gern. ;-))

>> BTW: Erstellst Du die Statistiken ausschließlich über den Hamster und wie
>> greifst du auf die Daten zu? Vermutlich kannst Due auch den Supersedes im
>> Header auswerten, was AFAICS mit der nntp-lib nicht möglich ist. :-/
> Bei Gruppen, die ich im Hamster habe, hole ich mir die Artikel - und
> zwar die ganzen - per OLE aus dem Hamster, das geht schneller als per
> NNTP, hat jedoch vom Artikelzugriff her weniger Möglichkeiten als NNTP,
> erlaubt jedoch eine Fernsteuerung des Hamsters über Python (benutze ich
> jedoch nicht). Bestimmte Header kannst Du doch mit nntplib.xhdr()
> holen. Soweit ich sehe, arbeitet Ngstat doch auch damit.

Ja, es wird die nntplib.py verwendet. Ich habe jetzt auch Dank deines
Anstoßes den relevanten Teil gefunden, in welchem die Header-Daten
übergeben werden:

(allheaders,idref)=newsstat3.getheaders(nntpgroup+'.'+nntpserver+'.!cache',[h_msgid,h_from,h_subject,h_lines,h_date,h_references,h_size,h_xnewsreader,h_xmailer,h_useragent],nntpgroup,nntponline)

Dabei bin ich mir nur noch nicht sicher, ob ich Supersedes einfach
hinzufügen kann oder in diesem Fall die !cache-File neu ertellt werden
muss. Ich werde das aber auf jeden Fall mal testen.


cu, Maik
--
250+ 3D Wallpaper: http://www.2prinz.de

40tude Dialog - Free Windows-Newsreader
Download: http://www.40tude.com/dialog/

NG: news:de.comm.software.40tude-dialog

Ralf Wachinger

unread,
May 24, 2005, 6:29:27 AM5/24/05
to
Maik Prinz schrieb:

> Oje, das sollte jetzt kein Aufruf zum Wettbewerb sein. Bei Deinen
> AFN-Stats kann ich
>
> | >> Ich wollte es aber auch bei einem Posting mit ca. 350 Lines belassen.
> | > Das sind schon ganz schön viele.
>
> BTW hat die Mozilla-Statistik (dcsm*) sogar 826 Lines. ;-/

Mein Statpaket Anfang Januar dürfte einige tausend Lines gehabt haben,
aber maßlose Übertreibung lernt man in Afn leicht :o)

>> Raw-Strings und gewöhnliche Strings lassen sich ganz normal verketten.
>> Pfade und Dateinamen können alle Zeichen enthalten, die auch das
>> Betriebssystem erlaubt.
>
> Das funktioniert jetzt soweit auch. Ich hatte zunächst ein
> Verständnisproblem, wo das r zu setzen ist. Anscheinend kann dieses nur
> direkt bei der Wertzuweisung z.B. filepfad=r'D:\Test' geschehen.

Das "r" ist nur bei Stringliteralen zu setzen, nicht bei Variablen. Es
erspart einem halt das Verdoppeln von Backslashes, weil Escape-Sequenzen
("\n" usw.) nicht mehr geparst werden. Bei RegExen würden Backslashes
ohne "r" sogar zu 4fach-Monstern anwachsen.

>> Er wird nicht überschrieben, sondern es gibt wird eine Ausnahme
>> ausgeworfen. Auf Vorhandensein überprüft man mit os.path.exists(), wobei
>> man als Parameter sowohl einen Ordner als auch eine Datei angeben kann.
>
> Super, dann werde ich damit noch eine Sicherheitsabfrage einbauen und
> ggf. den Ordner erstellen lassen.

Das ist ratsam. Bei Dateisystemoperationen sollte man immer auch an
Fehlermöglichkeiten denken und sie in seinem Code berücksichtigen.

>> Ja, das dürfte so funktionieren, allerdings ist es ein bisschen
>> ungewöhnlich, für jeden Schreibvorgang die Datei zu öffnen und wieder zu
>> schließen, statt öffnen vor dem ersten und schließen nach dem letzten
>> Schreibvorgang.
>
> So habe ich halt im Falle eines vorzeitigen Abbruchs dennoch Daten in
> der Datei. So hat man auch bei fehlendem useIDLE immer ein Resultat.

Von da her gesehen ist es sicherer. Allerdings geht der Inhalt der Datei
nicht einfach so verloren bzw. es muss nicht so sein. Es schaut nur so
aus, solange die Datei nicht geschlossen ist. Deshalb benutzt man
Try-Finally:

datei = open(...)

try:
# Wenn im Code im Try-Block eine Ausnahme auftritt, wird
# der Code im Finally-Block trotzdem noch ausgeführt.
finally:
datei.close()

Außerdem muss eine Ausnahme nicht zum Abbruch führen, wenn man sie
auffängt, nur mal z. B.:

try:
print >> datei, text
except IOError:
print text

Sollte hier ein Schreibvorgang in die Datei nicht klappen, wird
stattdessen in das IDLE-Fenster geschrieben.

Ausnahmen und Ausnahmebehandlung ist ein interessantes Konzept, mit dem
man sich beschäftigen sollte. Die ganzen Fehlermeldungen des
Interpreters sind ausgeworfene Ausnahmen, die ohne Ausnahmebehandlung
einfach zum Abbruch führen. Der Programmierer kann mit Try-Anweisungen
bestimmen, ob bzw. wo welche Ausnahmen abgefangen werden, und welche
Aktionen darauf erfolgen sollen (kontrollierte Programmbeendigung,
Abschlussaktionen, Alternativaktionen, Benutzereingaben usw.).

Wie weit ist Dir das Konzept vertraut?

> Ich hole nicht bei jeder Statistikerstellung Daten sondern lade nur ggf.
> neue dazu. Diese werden dann zusammen in eine Datei gespeichert von wo
> aus das abarbeiten der Daten erfolgt.

Achso, dann machst Du es ja im Prinzip wie ich. Ich speichere die Daten
allerdings als Postingtexte in einer indizierten Datei. Ist ja bisher
alles altmodisch sequentiell von der Platte verarbeitet worden, auch
weil mein bisheriger alter PC wenig Arbeitsspeicher für heutige
Verhältnisse hat. Erst der neue Code im Thread- und Zeitspannen-Stat-
Modul beschreitet neue Wege.

>> Ansonsten dürfte das Obige für Deine Zwecke wohl reichen.
>
> Tut es ja auch, ohne das irgendwelche Performance-Last zu merken ist.

Das obige bewirkt keine erkennbare Performance-Last, da es nicht so
viele Schreibvorgänge sind.

>> Ich habe auch schon darüber nachgedacht, mein Programm dergestalt
>> flexibler zu machen und bin am Schreiben einer Ausgabeklasse für
>> allgemeine Verwendung.
>
> Da geht es ja bei Dir um einiges weiter, da AFAIR sogar Stats für die
> Nutzung auf Webseiten geschrieben werden sollen.

Ja, automatische HTML-Dokument-Erstellung trage ich irgendwann für die
Zukunft in Gedanken. Ausgabe-Klassen statt Print-Anweisungen bringen ja
allgemein viel Flexibilität nach folgendem geplanten Muster (das
Konkrete nur mal als Beispiel), in dem die Ausgabe-Objekte - einmal
initialisiert - die Ausgaben an die gewünschten Ziele leiten:

ergebnisse = Ausgabe(dateiname = "Beispiel.txt")
meldung = Ausgabe(sys.stdout)
fehlermeldung = Ausgabe(sys.stderr, dateiname = "Fehler.log")
erstelleStats = Ausgabe(dateiname = "Stats.txt", modus = "a")

meldung("Verarbeitung startet")
ergebnisse(tabelle1)
ergebnisse(tabelle2)
meldung("Fertig")
erstellteStats("Am %s wurde %s erstellt." % (datum, ergebnisse.dateiname))

Die Meldungen gehen ins IDLE-Fenster, die Ergebnisse der Stat in die
Statdatei, die Fehlermeldungen in Rot ins IDLE-Fenster und zusätzlich in
eine Log-Datei, und eine fortlaufende Info-Datei der erstellten Stats
wird weitergeschrieben. Wenn man es mal anders will, ändert man einfach
die Kreierungzeilen der Ausgabe-Objekte.

>> Du musst bloß in Erinnerung behalten, dass Dein Script nun in lokaler
>> Zeit - also bei uns mitteleuropäischer Zeit - arbeitet, während AgtFind
>> und GoldFind immer in GMT arbeiten, was theoretisch zwar richtig, für
>> die Praxis aber verwirrend ist. Mein Programm statistiziert in MEZ mit
>> Beachtung der Sommer- und Winterzeit.
> ~~~~~~~~~~~~~~~~~~~~~~
> Lokal-Zeit heißt doch, dass *dies* auch berücksichtigt wird, oder?

Richtig.

> Ja, es wird die nntplib.py verwendet. Ich habe jetzt auch Dank deines
> Anstoßes den relevanten Teil gefunden, in welchem die Header-Daten
> übergeben werden:
>
> (allheaders,idref)=newsstat3.getheaders(nntpgroup+'.'+nntpserver+'.!cache',[h_msgid,h_from,h_subject,h_lines,h_date,h_references,h_size,h_xnewsreader,h_xmailer,h_useragent],nntpgroup,nntponline)
>
> Dabei bin ich mir nur noch nicht sicher, ob ich Supersedes einfach
> hinzufügen kann oder in diesem Fall die !cache-File neu ertellt werden
> muss. Ich werde das aber auf jeden Fall mal testen.

Ich hab mir mal den Code des originalen Ngstat angeschaut: Die Daten
werden gepicklet. Allgemein gilt: Pickle-Dateien sind zwar sehr gut zum
Speichern von Python-Datenstrukturen, aber genau das beschränkt auch
Änderungen der Datenstruktur. Wenn Du die Datenstruktur änderst, dann
stimmen die bisherigen gepickelten Daten von der Struktur her nicht mehr
mit den im Programm benutzen überein.

Maik Prinz

unread,
May 25, 2005, 3:00:23 PM5/25/05
to
*Ralf Wachinger* schrieb am Di, 24. Mai. 2005 um 12:29...

>> BTW hat die Mozilla-Statistik (dcsm*) sogar 826 Lines. ;-/
> Mein Statpaket Anfang Januar dürfte einige tausend Lines gehabt haben,
> aber maßlose Übertreibung lernt man in Afn leicht :o)

Das habe ich mitbekommen. ;-))

[os.path.exists()]


>> Super, dann werde ich damit noch eine Sicherheitsabfrage einbauen und
>> ggf. den Ordner erstellen lassen.
> Das ist ratsam. Bei Dateisystemoperationen sollte man immer auch an
> Fehlermöglichkeiten denken und sie in seinem Code berücksichtigen.

Das sehe ich genauso. Das fängt bei mir schon bei der Einstellung des
auszuwertenden Monats an, wo auf fscalhe Eingabe hingewiesen wird und
hört dann natürlich (nicht) bei den Pfadangaben auf.

[Erweiterte Ausnahmebehandlung]


> Ausnahmen und Ausnahmebehandlung ist ein interessantes Konzept, mit dem
> man sich beschäftigen sollte. Die ganzen Fehlermeldungen des
> Interpreters sind ausgeworfene Ausnahmen, die ohne Ausnahmebehandlung
> einfach zum Abbruch führen. Der Programmierer kann mit Try-Anweisungen
> bestimmen, ob bzw. wo welche Ausnahmen abgefangen werden, und welche
> Aktionen darauf erfolgen sollen (kontrollierte Programmbeendigung,
> Abschlussaktionen, Alternativaktionen, Benutzereingaben usw.).
> Wie weit ist Dir das Konzept vertraut?

Ich hatte schon vor deinem letzten Artikel darüber gelesen und finde es
durchaus interessant und wertvoll in der Praxis.

>>> Ansonsten dürfte das Obige für Deine Zwecke wohl reichen.
>>
>> Tut es ja auch, ohne das irgendwelche Performance-Last zu merken ist.
> Das obige bewirkt keine erkennbare Performance-Last, da es nicht so
> viele Schreibvorgänge sind.

Es sind bei mir pro Statistikerstellung bis zu 48 Schreibvorgänge. :)

>>> Ich habe auch schon darüber nachgedacht, mein Programm dergestalt
>>> flexibler zu machen und bin am Schreiben einer Ausgabeklasse für
>>> allgemeine Verwendung.
>>
>> Da geht es ja bei Dir um einiges weiter, da AFAIR sogar Stats für die
>> Nutzung auf Webseiten geschrieben werden sollen.
> Ja, automatische HTML-Dokument-Erstellung trage ich irgendwann für die
> Zukunft in Gedanken. Ausgabe-Klassen statt Print-Anweisungen bringen ja
> allgemein viel Flexibilität nach folgendem geplanten Muster (das
> Konkrete nur mal als Beispiel), in dem die Ausgabe-Objekte - einmal
> initialisiert - die Ausgaben an die gewünschten Ziele leiten:

Es ist für mich immer wieder Interessant solche Beispiele zu sehen,
welche einen auch oft zusätzlich auf neue Ideen bringt. :-)

[Auswertung der Supersedes mittels nntplib.xhdr()]


> Ich hab mir mal den Code des originalen Ngstat angeschaut: Die Daten
> werden gepicklet. Allgemein gilt: Pickle-Dateien sind zwar sehr gut zum
> Speichern von Python-Datenstrukturen, aber genau das beschränkt auch
> Änderungen der Datenstruktur. Wenn Du die Datenstruktur änderst, dann
> stimmen die bisherigen gepickelten Daten von der Struktur her nicht mehr
> mit den im Programm benutzen überein.

So ganz bin ich mit den Vorgängen beim einlesen der Daten (Pickle) nicht
vertraut. Es überrascht mich aber dennoch, dass es offensichtlich keine
Probleme mit der Datenstruktur zu geben scheint. AFAICS werden hierbei
die Supersedes sogar von Anfang an hinzugefügt, solange es die Haltezeit
des Servers zulässt.

Ralf Wachinger

unread,
May 26, 2005, 8:31:31 AM5/26/05
to
Maik Prinz schrieb:

>> Mein Statpaket Anfang Januar dürfte einige tausend Lines gehabt haben,
>> aber maßlose Übertreibung lernt man in Afn leicht :o)
>
> Das habe ich mitbekommen. ;-))

Die Maßlosigkeit wird mich wohl ab Juni noch mehr überkommen, wo ich per
Kabelnetz Daten einsaugen kann und nicht mehr per analogem Modem :o)

>> Das ist ratsam. Bei Dateisystemoperationen sollte man immer auch an
>> Fehlermöglichkeiten denken und sie in seinem Code berücksichtigen.
>
> Das sehe ich genauso. Das fängt bei mir schon bei der Einstellung des
> auszuwertenden Monats an, wo auf fscalhe Eingabe hingewiesen wird und
> hört dann natürlich (nicht) bei den Pfadangaben auf.

Ich habe in meinem Programm eine automatische Fortschreibung eingebaut.
Jede Auswertungszeiteinheit (Monat, Quartal, Jahr usw.) und jede
Auswertungseinheit (z. B. Gruppe, Hierarchie, Teilhierarchie) ist in
einem eigenen Verzeichnis organisiert. Per Menüpunkt werden auf einen
Schlag für den jeweiligen neuen Monat die Verzeichnisse für alle
Auswertungseinheiten erstellt und die Ini-Dateien kopiert und bzgl. der
Zeitangaben geändert bzw. fortgeschrieben.

Wenn es um Dateien und Verzeichnisse geht, hat ein Oberflächenprogramm
natürlich seine Vorteile mit Datei-Öffnen-, Datei-Speichern- und
Ordner-Wahl-Dialogfenstern.

> [Erweiterte Ausnahmebehandlung]


> Ich hatte schon vor deinem letzten Artikel darüber gelesen und finde es
> durchaus interessant und wertvoll in der Praxis.

In Python ist das Ausnahme-Konzept nicht nur wertvoll, sondern auch von
essentieller Bedeutung, weil Ausnahmen für alles Mögliche ausgeworfen
werden. Ich denke z. B. an ValueError oder IndexError bei Listen,
KeyError bei Dictionaries, StopIteration bei Iteration, diese Ausnahmen
sind Alltäglichkeiten.

>> Das obige bewirkt keine erkennbare Performance-Last, da es nicht so
>> viele Schreibvorgänge sind.
>
> Es sind bei mir pro Statistikerstellung bis zu 48 Schreibvorgänge. :)

Tiny Peanuts, man wirds wohl erst ab einigen 100.000 Schreibvorgängen
wirklich merken.

>>> Da geht es ja bei Dir um einiges weiter, da AFAIR sogar Stats für die
>>> Nutzung auf Webseiten geschrieben werden sollen.
>> Ja, automatische HTML-Dokument-Erstellung trage ich irgendwann für die
>> Zukunft in Gedanken. Ausgabe-Klassen statt Print-Anweisungen bringen ja
>> allgemein viel Flexibilität nach folgendem geplanten Muster (das
>> Konkrete nur mal als Beispiel), in dem die Ausgabe-Objekte - einmal
>> initialisiert - die Ausgaben an die gewünschten Ziele leiten:
>
> Es ist für mich immer wieder Interessant solche Beispiele zu sehen,
> welche einen auch oft zusätzlich auf neue Ideen bringt. :-)

Inzwischen habe ich meine Ausgabenklassen verbessert. Das Zielobjekt,
das man bei der Print-Anweisung angibt, kann ja jedes datei-ähnliche
Objekt mit einer Write-Methode sein, also habe ich meinen
Ausgabeobjekten eine Write-Methode verpasst, so dass sie mit Print
benutzt werden können. Die Vorteile:
* Die Ausgabe erfolgt immer einheitlich über die Print-Anweisung, egal
welches Zielobjekt es ist (Konsole, Datei, Tkinter-Textfenster oder eine
Kombination).
* Sofortige Ausgabe oder gepufferte spätere Ausgabe sind möglich.
* Standardaktionen wie z. B. mögliche Abfrage, ob eine existierende
Datei überschrieben werden soll oder die Ausnahmebehandlung müssen nicht
jedesmal neu programmiert werden.
* Einheitliches Ausgabe-(Hilfs)-Interface von Kommandozeilenprogrammen
(print, raw_input) und Tkinter-GUI-Programmen (textfenster.insert,
tkMessageBox).
* Leichte Änderung der tatsächlichen Ausgabeziele, weil in der
Print-Anweisung praktisch die Kategorie und nicht das direkte Ziel
steht. Wo es tatsächlich hingeht, legt man am Anfang fest.

statusmeldung = Konsolenausgabe()
fehlermeldung = Konsolenausgabe(sys.stderr)
ergebnis = Ausgabe(Konsolenausgabe(), Dateiausgabe(r"E:\Statistiken\Test.txt"))

print >> statusmeldung, "Verarbeitung startet"
print >> ergebnis, tabelle

Wenn man sich nun umentscheidet, die Ergebnisse nur noch in eine Datei
auszugeben und erst am Ende gesammelt, und die Fehler auch zu loggen,
dann braucht man nur die Deklarationen ändern, die Print-Anweisungen
ändern sich nicht:

fehlermeldung = Ausgabe(Konsolenausgabe(sys.stderr), Dateiausgabe(r"E:\Statistiken\Fehler.log"))
ergebnis = Dateiausgabe(r"E:\Statistiken\Test.txt", puffern = True)
print >> ergebnis, tabelle
ergebnis.writebuffer()


> [Auswertung der Supersedes mittels nntplib.xhdr()]

> So ganz bin ich mit den Vorgängen beim einlesen der Daten (Pickle) nicht
> vertraut. Es überrascht mich aber dennoch, dass es offensichtlich keine
> Probleme mit der Datenstruktur zu geben scheint. AFAICS werden hierbei
> die Supersedes sogar von Anfang an hinzugefügt, solange es die Haltezeit
> des Servers zulässt.

Klar, alles was Du neu holst, pickelst und wieder entpickelst, haben ja
die neuen Supersedes-Header-Daten. Beim vorhandenen Entpickelten kommt
es bzgl. des Auftretens von Fehlern darauf an, wie die Daten
strukturiert sind, da gibt es natürlich noch keine Supersedes-Daten.

Maik Prinz

unread,
May 27, 2005, 8:16:11 AM5/27/05
to
*Ralf Wachinger* schrieb am Do, 26. Mai. 2005 um 14:31...

>>> Das ist ratsam. Bei Dateisystemoperationen sollte man immer auch an
>>> Fehlermöglichkeiten denken und sie in seinem Code berücksichtigen.
>> Das sehe ich genauso. Das fängt bei mir schon bei der Einstellung des
>> auszuwertenden Monats an, wo auf fscalhe Eingabe hingewiesen wird und
>> hört dann natürlich (nicht) bei den Pfadangaben auf.
[...]

> Wenn es um Dateien und Verzeichnisse geht, hat ein Oberflächenprogramm
> natürlich seine Vorteile mit Datei-Öffnen-, Datei-Speichern- und
> Ordner-Wahl-Dialogfenstern.

Hast Du derartiges auch selbst im Einsatz? An den Beispielskripten sieht
man ja, dass mit Python einiges möglich ist - soweit bin ich aber noch
lange nicht.

>> [Erweiterte Ausnahmebehandlung]
>> Ich hatte schon vor deinem letzten Artikel darüber gelesen und finde es
>> durchaus interessant und wertvoll in der Praxis.
> In Python ist das Ausnahme-Konzept nicht nur wertvoll, sondern auch von
> essentieller Bedeutung, weil Ausnahmen für alles Mögliche ausgeworfen
> werden. Ich denke z. B. an ValueError oder IndexError bei Listen,
> KeyError bei Dictionaries, StopIteration bei Iteration, diese Ausnahmen
> sind Alltäglichkeiten.

Was spricht eigentlich bei der Verzeichniserstellung gegen os.makedirs()?

>>> Das obige bewirkt keine erkennbare Performance-Last, da es nicht so
>>> viele Schreibvorgänge sind.
>> Es sind bei mir pro Statistikerstellung bis zu 48 Schreibvorgänge. :)
> Tiny Peanuts, man wirds wohl erst ab einigen 100.000 Schreibvorgängen
> wirklich merken.

Wieviele Schreibvorgänge sind es den bei Dir so im Schnitt?

[Statistik-Ausgabe]


>> Es ist für mich immer wieder Interessant solche Beispiele zu sehen,
>> welche einen auch oft zusätzlich auf neue Ideen bringt. :-)
> Inzwischen habe ich meine Ausgabenklassen verbessert. Das Zielobjekt,
> das man bei der Print-Anweisung angibt, kann ja jedes datei-ähnliche
> Objekt mit einer Write-Methode sein, also habe ich meinen
> Ausgabeobjekten eine Write-Methode verpasst, so dass sie mit Print
> benutzt werden können. Die Vorteile:
> * Die Ausgabe erfolgt immer einheitlich über die Print-Anweisung, egal
> welches Zielobjekt es ist (Konsole, Datei, Tkinter-Textfenster oder eine
> Kombination).

Hast Du für Tkinter-Textfenster mal ein kleines Beispiel?

> * Standardaktionen wie z. B. mögliche Abfrage, ob eine existierende
> Datei überschrieben werden soll oder die Ausnahmebehandlung müssen nicht
> jedesmal neu programmiert werden.

Das wäre natürlich auch hier optimal, ist mir aber noch nicht geläufig.

> * Leichte Änderung der tatsächlichen Ausgabeziele, weil in der
> Print-Anweisung praktisch die Kategorie und nicht das direkte Ziel
> steht. Wo es tatsächlich hingeht, legt man am Anfang fest.
> statusmeldung = Konsolenausgabe()
> fehlermeldung = Konsolenausgabe(sys.stderr)
> ergebnis = Ausgabe(Konsolenausgabe(), Dateiausgabe(r"E:\Statistiken\Test.txt"))
> print >> statusmeldung, "Verarbeitung startet"
> print >> ergebnis, tabelle

Das ist vom Grundkonzept alles so schön anzuschauen. :-))

> Wenn man sich nun umentscheidet, die Ergebnisse nur noch in eine Datei
> auszugeben und erst am Ende gesammelt, und die Fehler auch zu loggen,
> dann braucht man nur die Deklarationen ändern, die Print-Anweisungen
> ändern sich nicht:

... was das ganze natürlich flexibel und benutzerfreundlich macht. Das
ich für die Integration der Supersedes nicht mal eine Halbe Stunde
gebraucht habe, zeugt für meine Verhältnisse auch schon für leichtes
Handling. ;-)

>> [Auswertung der Supersedes mittels nntplib.xhdr()]
>> So ganz bin ich mit den Vorgängen beim einlesen der Daten (Pickle) nicht
>> vertraut. Es überrascht mich aber dennoch, dass es offensichtlich keine
>> Probleme mit der Datenstruktur zu geben scheint. AFAICS werden hierbei
>> die Supersedes sogar von Anfang an hinzugefügt, solange es die Haltezeit
>> des Servers zulässt.
> Klar, alles was Du neu holst, pickelst und wieder entpickelst, haben ja
> die neuen Supersedes-Header-Daten. Beim vorhandenen Entpickelten kommt
> es bzgl. des Auftretens von Fehlern darauf an, wie die Daten
> strukturiert sind, da gibt es natürlich noch keine Supersedes-Daten.

Ich habe mal von einem recht neuen Server die Daten nachgeladen, wobei
überall Artikel 556-589 neu geladen wurden ...

| Checking headers
| loading Message-ID (556-589)...
| loading From (556-589)...
| loading Subject (556-589)...
| loading Lines (556-589)...
| loading Date (556-589)...
| loading References (556-589)...
| loading Bytes (556-589)...
| loading X-Newsreader (556-589)...
| loading X-Mailer (556-589)...
| loading User-Agent (556-589)...
| loading Supersedes (2-589)...
| Saving new cache...

... bei den Supersedes waren es dagegen die Artikel 2-589. Es hängt also
maßgeblich von der Haltezeit des Newsservers ab, ob die Supersedes
nachträglich eingelesen werden können.

Ralf Wachinger

unread,
Jun 2, 2005, 6:36:04 PM6/2/05
to
Maik Prinz schrieb:

>> Wenn es um Dateien und Verzeichnisse geht, hat ein Oberflächenprogramm
>> natürlich seine Vorteile mit Datei-Öffnen-, Datei-Speichern- und
>> Ordner-Wahl-Dialogfenstern.
>
> Hast Du derartiges auch selbst im Einsatz? An den Beispielskripten sieht
> man ja, dass mit Python einiges möglich ist - soweit bin ich aber noch
> lange nicht.

Ich habe Datei-Öffnen, -Speichern und Ordner-Wahl-Dialogfenster im
Einsatz, ist ja nicht schwer in Tkinter. Allerdings ist die Umstellung
auf GUI-Programme, wenn man bisher nur Konsolenprogramme erstellt hat,
nicht gerade leicht.

>> In Python ist das Ausnahme-Konzept nicht nur wertvoll, sondern auch von
>> essentieller Bedeutung, weil Ausnahmen für alles Mögliche ausgeworfen
>> werden. Ich denke z. B. an ValueError oder IndexError bei Listen,
>> KeyError bei Dictionaries, StopIteration bei Iteration, diese Ausnahmen
>> sind Alltäglichkeiten.
>
> Was spricht eigentlich bei der Verzeichniserstellung gegen os.makedirs()?

Im Grunde nichts. Aber willst Du wirklich mehrere Verzeichnisebenen
anlegen?

>> Tiny Peanuts, man wirds wohl erst ab einigen 100.000 Schreibvorgängen
>> wirklich merken.
>
> Wieviele Schreibvorgänge sind es den bei Dir so im Schnitt?

Kann ich nicht genau sagen, bei langen Stats dürften höchstens mal ein
paar Hundert zusammenkommen.

>> Inzwischen habe ich meine Ausgabenklassen verbessert. Das Zielobjekt,
>> das man bei der Print-Anweisung angibt, kann ja jedes datei-ähnliche
>> Objekt mit einer Write-Methode sein, also habe ich meinen
>> Ausgabeobjekten eine Write-Methode verpasst, so dass sie mit Print
>> benutzt werden können. Die Vorteile:
>> * Die Ausgabe erfolgt immer einheitlich über die Print-Anweisung, egal
>> welches Zielobjekt es ist (Konsole, Datei, Tkinter-Textfenster oder eine
>> Kombination).
>
> Hast Du für Tkinter-Textfenster mal ein kleines Beispiel?

Ja, erstell eine Datei mit folgendem Code:

--------------------------- Code schnipp ----------------------------

from Tkconstants import *
import Tkinter
from ScrolledText import ScrolledText

root = Tkinter.Tk()
root.title("Maiks Textfenster")
textfenster = ScrolledText(root, wrap = WORD, width = 80, height = 40, background = "white")
textfenster.insert(END, "Hallo, ich bin Dein erstes Textfenster!")
textfenster.pack()
root.mainloop()

--------------------------- Code schnapp ----------------------------

Das ist natürlich nur ein *sehr* einfaches Tkinter-Programm.

>> * Standardaktionen wie z. B. mögliche Abfrage, ob eine existierende
>> Datei überschrieben werden soll oder die Ausnahmebehandlung müssen nicht
>> jedesmal neu programmiert werden.
>
> Das wäre natürlich auch hier optimal, ist mir aber noch nicht geläufig.

Es wäre lohnend, wenn Du Dich mal mit dem Ausnahmekonzept in Python
beschäftigst. Python tut es da C++ gleich, das das gleiche grundlegende
Konzept hat.

>> * Leichte Änderung der tatsächlichen Ausgabeziele, weil in der
>> Print-Anweisung praktisch die Kategorie und nicht das direkte Ziel
>> steht. Wo es tatsächlich hingeht, legt man am Anfang fest.
>> statusmeldung = Konsolenausgabe()
>> fehlermeldung = Konsolenausgabe(sys.stderr)
>> ergebnis = Ausgabe(Konsolenausgabe(), Dateiausgabe(r"E:\Statistiken\Test.txt"))
>> print >> statusmeldung, "Verarbeitung startet"
>> print >> ergebnis, tabelle
>
> Das ist vom Grundkonzept alles so schön anzuschauen. :-))

Allerdings. Und es anzuwenden ist auch nicht allzu schwer, wenn man das
entsprechende Modul dafür fertig zum Anwenden hat.

>> Wenn man sich nun umentscheidet, die Ergebnisse nur noch in eine Datei
>> auszugeben und erst am Ende gesammelt, und die Fehler auch zu loggen,
>> dann braucht man nur die Deklarationen ändern, die Print-Anweisungen
>> ändern sich nicht:
>
> ... was das ganze natürlich flexibel und benutzerfreundlich macht. Das
> ich für die Integration der Supersedes nicht mal eine Halbe Stunde
> gebraucht habe, zeugt für meine Verhältnisse auch schon für leichtes
> Handling. ;-)

Ja, aber das war doch eine ganz anders gelagerte Sache, oder?

> Ich habe mal von einem recht neuen Server die Daten nachgeladen, wobei
> überall Artikel 556-589 neu geladen wurden ...
>
> | Checking headers
> | loading Message-ID (556-589)...
> | loading From (556-589)...
> | loading Subject (556-589)...
> | loading Lines (556-589)...
> | loading Date (556-589)...
> | loading References (556-589)...
> | loading Bytes (556-589)...
> | loading X-Newsreader (556-589)...
> | loading X-Mailer (556-589)...
> | loading User-Agent (556-589)...
> | loading Supersedes (2-589)...
> | Saving new cache...
>
> ... bei den Supersedes waren es dagegen die Artikel 2-589. Es hängt also
> maßgeblich von der Haltezeit des Newsservers ab, ob die Supersedes
> nachträglich eingelesen werden können.

Klar, so gesehen. Aber dass die neuen Header so nahtlos in die
vorhandenen Datenstrukturen integriert werden konnten, ist dem
Programmierer von Ngstat zu verdanken.

Maik Prinz

unread,
Jun 3, 2005, 1:14:50 PM6/3/05
to
*Ralf Wachinger* schrieb am Fr, 03. Jun. 2005 um 0:36...

>>> Wenn es um Dateien und Verzeichnisse geht, hat ein Oberflächenprogramm
>>> natürlich seine Vorteile mit Datei-Öffnen-, Datei-Speichern- und
>>> Ordner-Wahl-Dialogfenstern.
>> Hast Du derartiges auch selbst im Einsatz? An den Beispielskripten sieht
>> man ja, dass mit Python einiges möglich ist - soweit bin ich aber noch
>> lange nicht.
> Ich habe Datei-Öffnen, -Speichern und Ordner-Wahl-Dialogfenster im
> Einsatz, ist ja nicht schwer in Tkinter. Allerdings ist die Umstellung
> auf GUI-Programme, wenn man bisher nur Konsolenprogramme erstellt hat,
> nicht gerade leicht.

Ist es wirklich viel schwieriger als die kombinierte Ausgabe in GUI und
File? Wirklich kompliziert wird es wahrscheinlich erst, wenn Du meine
Idee zur Einbindung von Tkinter in ngstat hörst.
Ich wollte so etwas wie einen Konfigurationsdialog daraus programmieren,
welcher dann mittels ausgelesener Daten aus einer Datei z.B. Drop-Down
Listen mit verschiedenen Newsgroups, Checkboxen mit verschiedenen
Parametern und andere Einstellmöglichkeiten bietet. :)

>> Was spricht eigentlich bei der Verzeichniserstellung gegen os.makedirs()?
> Im Grunde nichts. Aber willst Du wirklich mehrere Verzeichnisebenen
> anlegen?

.. ich nicht unbedingt, aber bei Weitergabe des Skripts wäre das nicht
ausgeschlossen.

>> Hast Du für Tkinter-Textfenster mal ein kleines Beispiel?
> Ja, erstell eine Datei mit folgendem Code:

Danke, das sieht ja zunächst recht simple aus

> --------------------------- Code schnipp ----------------------------
> from Tkconstants import *
> import Tkinter
> from ScrolledText import ScrolledText
> root = Tkinter.Tk()
> root.title("Maiks Textfenster")
> textfenster = ScrolledText(root, wrap = WORD, width = 80, height = 40, background = "white")
> textfenster.insert(END, "Hallo, ich bin Dein erstes Textfenster!")

Ich denke mal, diese Daten lassen sich auch fortlaufend erweitern

> textfenster.pack()
> root.mainloop()

Welche elementare Bedeutung haben diese beiden...?

> --------------------------- Code schnapp ----------------------------
> Das ist natürlich nur ein *sehr* einfaches Tkinter-Programm.

Sicherlich - da sind Dropdown-Felder, Listboxen u.s.w. sicherlich schon
Anspruchsvoller. ;)

[...]


>>| loading User-Agent (556-589)...
>>| loading Supersedes (2-589)...
>>| Saving new cache...
>> ... bei den Supersedes waren es dagegen die Artikel 2-589. Es hängt also
>> maßgeblich von der Haltezeit des Newsservers ab, ob die Supersedes
>> nachträglich eingelesen werden können.
> Klar, so gesehen. Aber dass die neuen Header so nahtlos in die
> vorhandenen Datenstrukturen integriert werden konnten, ist dem
> Programmierer von Ngstat zu verdanken.

Insgesamt staune ich auch immer wieder, was ngstat vom Grundkonstrukt
her zu leisten vermag. Ohne dies wäre meine Statsspielerei[tm] überhaupt
nicht möglich gewesen.

Ralf Wachinger

unread,
Jun 5, 2005, 7:04:10 AM6/5/05
to
Maik Prinz schrieb:

> Ist es wirklich viel schwieriger als die kombinierte Ausgabe in GUI und
> File?

Ja, z. B. meine Ausgabeklassen setzen ja schon ein
Tkinter-Rahmenprogramm mit den entsprechenden Fensterobjekten voraus.
Hinter der GUI-Programmierung steckt ja viel mehr als hinter der
Konsolenprogrammierung.

> Wirklich kompliziert wird es wahrscheinlich erst, wenn Du meine
> Idee zur Einbindung von Tkinter in ngstat hörst.
> Ich wollte so etwas wie einen Konfigurationsdialog daraus programmieren,
> welcher dann mittels ausgelesener Daten aus einer Datei z.B. Drop-Down
> Listen mit verschiedenen Newsgroups, Checkboxen mit verschiedenen
> Parametern und andere Einstellmöglichkeiten bietet. :)

Das ist in der Tat komplizierter. Na gut, Tkinter ist immer noch relativ
einfach zu handhaben verglichen mit anderen GUI-Bibliotheken. Allerdings
kann man mit Tkinter nicht allzu viel machen, deshalb gibt es auch die
Erweiterung Tix.

> .. ich nicht unbedingt, aber bei Weitergabe des Skripts wäre das nicht
> ausgeschlossen.

Ja, da kann das schon vorkommen. Du kannst ja os.makedirs() mal
austesten.

> Danke, das sieht ja zunächst recht simple aus

Es ist recht simpel, weil da ja äußerst wenig Funktionalität drin ist.
Wenn Du mal ein richtiges Tkinter-Programm schreibst, wirst Du selber
merken, wie viel Du da bedenken und programmieren musst.

> Ich denke mal, diese Daten lassen sich auch fortlaufend erweitern

Ja, aber baue nicht darauf, das ist wirklich nur ein winziges Beispiel.

> Welche elementare Bedeutung haben diese beiden...?

Die Mainloop ist ein Grundprinzip der GUI-Programmierung. Ein
GUI-Programm läuft in einer Schleife, denn es soll ja nur beendet
werden, wenn der Nutzer es will. Und die Pack-Methode gehört zu einem
Geometriemanager, der die Platzierung der Unterelemente in den Fenstern
(in Tkinter spricht man von Widgets, kommt von Window-Gadget) managet.

> Sicherlich - da sind Dropdown-Felder, Listboxen u.s.w. sicherlich schon
> Anspruchsvoller. ;)

Allerdings. Und jedes Widget hat seine eigenen Eigenschaften und
Methoden. Schau Dir halt in den Python-Manuals unter dem Stichwort "Tk"
nach. Da sind auch weiterführende Links genannt.

> [...]


> Insgesamt staune ich auch immer wieder, was ngstat vom Grundkonstrukt
> her zu leisten vermag. Ohne dies wäre meine Statsspielerei[tm] überhaupt
> nicht möglich gewesen.

Ja, ein gutes Grundkonzept ist sehr viel wert.

Maik Prinz

unread,
Jun 5, 2005, 1:19:22 PM6/5/05
to
*Ralf Wachinger* schrieb am So, 05. Jun. 2005 um 13:04...
[...]

>> Sicherlich - da sind Dropdown-Felder, Listboxen u.s.w. sicherlich schon
>> Anspruchsvoller. ;)
> Allerdings. Und jedes Widget hat seine eigenen Eigenschaften und
> Methoden. Schau Dir halt in den Python-Manuals unter dem Stichwort "Tk"
> nach. Da sind auch weiterführende Links genannt.

Danke für deine ausführlichen Erklärungen. Ich werde mich Stück für
Stück vorarbeiten und versuchen Tkinter sinnvoll einzusetzen. Zu Python
allgemein habe ich ein IMO gutes Manual als PDF in deutsch. Ich hoffe
auch zu diesem Thema etwas für mich verständliches zu finden. :-)

>> [...]
>> Insgesamt staune ich auch immer wieder, was ngstat vom Grundkonstrukt
>> her zu leisten vermag. Ohne dies wäre meine Statsspielerei[tm] überhaupt
>> nicht möglich gewesen.
> Ja, ein gutes Grundkonzept ist sehr viel wert.

Dennoch habe ich im Moment noch ein kleines Problem, welches ich einfach
nicht lösen kann. Und zwar geht es um den letzten Teil meiner Statistik
mit den Newbies. Wenn ich z.B. Heute nachträglich eine Statistik für den
Februar in dieser Gruppe erstelle, bin ich natürlich auch als ein Newbie
gelistet, wobei aber _alle_ Postings gezählt werden, welche ich in der
Zwischenzeit geschrieben habe. Alle Versuche für den Posting-Count nur
die Artikel des jeweiligen Monats zu berücksichtigen, schlugen bislang
leider fehl. :-(

Ralf Wachinger

unread,
Jun 7, 2005, 5:22:13 PM6/7/05
to
Maik Prinz schrieb:

> Danke für deine ausführlichen Erklärungen. Ich werde mich Stück für
> Stück vorarbeiten und versuchen Tkinter sinnvoll einzusetzen. Zu Python
> allgemein habe ich ein IMO gutes Manual als PDF in deutsch. Ich hoffe
> auch zu diesem Thema etwas für mich verständliches zu finden. :-)

Dann wünsche ich Dir mal viel Erfolg beim Lernen.

> Dennoch habe ich im Moment noch ein kleines Problem, welches ich einfach
> nicht lösen kann. Und zwar geht es um den letzten Teil meiner Statistik
> mit den Newbies. Wenn ich z.B. Heute nachträglich eine Statistik für den
> Februar in dieser Gruppe erstelle, bin ich natürlich auch als ein Newbie
> gelistet, wobei aber _alle_ Postings gezählt werden, welche ich in der
> Zwischenzeit geschrieben habe. Alle Versuche für den Posting-Count nur
> die Artikel des jeweiligen Monats zu berücksichtigen, schlugen bislang
> leider fehl. :-(

Dann heißt es halt für Dich, den Quellcode weiter zu ergründen. Ich
nehme an, Du stehst nicht mit dem Autor in Verbindung. Könnte er Dir
denn nicht bei schwierigen Problemen mit Ngstat weiterhelfen?

Maik Prinz

unread,
Jun 10, 2005, 5:41:00 PM6/10/05
to
*Ralf Wachinger* schrieb am Di, 07. Jun. 2005 um 23:22...
> Maik Prinz schrieb:
[Vertiefung der Kenntnisse im Umgang mit Python]

> Dann wünsche ich Dir mal viel Erfolg beim Lernen.

... danke Dir für diese Anteilnahme. ;-)

[Stockende Weiterentwicklung von NgStat]

> Dann heißt es halt für Dich, den Quellcode weiter zu ergründen.

Dito ... ganz nebenbei hilft das dann auch noch beim lernen. :)

> Ich nehme an, Du stehst nicht mit dem Autor in Verbindung. Könnte er
> Dir denn nicht bei schwierigen Problemen mit Ngstat weiterhelfen?

Ich halte leider keinen Kontakt zu Stephan. Ein Versuch wäre es aber
wohl allemal wert - vermutlich weiß er nicht mal welche Ausmaße sein
NgStat-Skript inzwischen angenommen hat. *g*

Ralf Wachinger

unread,
Jun 11, 2005, 9:54:20 AM6/11/05
to
Maik Prinz schrieb:

> [Stockende Weiterentwicklung von NgStat]
>> Dann heißt es halt für Dich, den Quellcode weiter zu ergründen.
>
> Dito ... ganz nebenbei hilft das dann auch noch beim lernen. :)

Es ist wirklich so, dass man in einem konkreten Projekt Etliches weiter
lernen kann, was man in Tutorials, Dokus und Trockenübungen nicht so
mitkriegt.

>> Ich nehme an, Du stehst nicht mit dem Autor in Verbindung. Könnte er
>> Dir denn nicht bei schwierigen Problemen mit Ngstat weiterhelfen?
>
> Ich halte leider keinen Kontakt zu Stephan. Ein Versuch wäre es aber
> wohl allemal wert - vermutlich weiß er nicht mal welche Ausmaße sein
> NgStat-Skript inzwischen angenommen hat. *g*

Das kann ich mir denken. Es kann sich ja eine positive
Feedback-Situation entwickeln.

0 new messages