Seite 1 von 2

Ladezeiten bei urllib messen

Verfasst: Mittwoch 29. April 2009, 18:04
von bankkind
Hallo leute,

Kann man irgendwie die Ladezeiten von urllib messen? Um eine art Mini-Monitoring zu basteln? bzw. wird auch etwas zurückgegeben, wenn das Laden der Seite fehlschlägt? Kann mir jemand helfen?

bankkind

Verfasst: Mittwoch 29. April 2009, 18:13
von snafu
[mod]timeit[/mod]

Verfasst: Mittwoch 29. April 2009, 18:18
von Leonidas
``timeit`` ist eher zum Benchmarken von Code-Snippseln, also etwas was der Programmierer bei Profiling tut. Zum Überwachen der Dauer die Produktivcode benötigt würde man eher zu ``time`` greifen.

Verfasst: Mittwoch 29. April 2009, 18:49
von snafu
Naja, mein Ansatz wäre halt dieser:

Code: Alles auswählen

In [30]: setup = 'import urllib'

In [31]: cmd = 'urllib.urlopen("http://www.ebay.de/")'

In [32]: timer = timeit.Timer(cmd, setup)

In [33]: print '%.2f seconds' % timer.timeit(number=1)
0.51 seconds

Verfasst: Mittwoch 29. April 2009, 19:42
von bankkind
Dieses Script hilft schon mal sehr! Danke.

Aber wie baue ich mir da jetzt mal nen TimeOut rein?

Verfasst: Mittwoch 29. April 2009, 19:48
von Leonidas
Du kannst dem Socket über ``settimeout`` einen Timeout angeben.

Verfasst: Mittwoch 29. April 2009, 21:00
von bankkind
snafu hat geschrieben:Naja, mein Ansatz wäre halt dieser:

Code: Alles auswählen

In [30]: setup = 'import urllib'

In [31]: cmd = 'urllib.urlopen("http://www.ebay.de/")'

In [32]: timer = timeit.Timer(cmd, setup)

In [33]: print '%.2f seconds' % timer.timeit(number=1)
0.51 seconds
Hey nochmal... ich habe doch noch einige probleme mit dem Script, bei mir bricht es teilweise noch ab ausserdem habe ich ein Verständnisproblem mit Zeile 6 aus unten stehendem Code

Code: Alles auswählen

setup = 'import urllib'
cmd = 'urllib.urlopen("' + url + '")'

for i in range(3):
    timer = timeit.Timer(cmd, setup)
    print '%.2f' % timer.timeit(number=1)

Code: Alles auswählen

Traceback (most recent call last):
  File "urltime.py", line 11, in <module>
    print '%.2f' % timer.timeit(number=1)
  File "C:\Python26\lib\timeit.py", line 193, in timeit
    timing = self.inner(it, self.timer)
  File "<timeit-src>", line 6, in inner
  File "C:\Python26\lib\urllib.py", line 87, in urlopen
    return opener.open(url)
  File "C:\Python26\lib\urllib.py", line 203, in open
    return getattr(self, name)(url)
  File "C:\Python26\lib\urllib.py", line 358, in open_http
    return self.http_error(url, fp, errcode, errmsg, headers)
  File "C:\Python26\lib\urllib.py", line 371, in http_error
    result = method(url, fp, errcode, errmsg, headers)
  File "C:\Python26\lib\urllib.py", line 636, in http_error_302
    data)
  File "C:\Python26\lib\urllib.py", line 651, in redirect_internal
    return self.open(newurl)
  File "C:\Python26\lib\urllib.py", line 203, in open
    return getattr(self, name)(url)
  File "C:\Python26\lib\urllib.py", line 358, in open_http
    return self.http_error(url, fp, errcode, errmsg, headers)
  File "C:\Python26\lib\urllib.py", line 371, in http_error
    result = method(url, fp, errcode, errmsg, headers)
  File "C:\Python26\lib\urllib.py", line 636, in http_error_302
    data)
  File "C:\Python26\lib\urllib.py", line 651, in redirect_internal
    return self.open(newurl)
  File "C:\Python26\lib\urllib.py", line 203, in open
    return getattr(self, name)(url)
  File "C:\Python26\lib\urllib.py", line 358, in open_http
    return self.http_error(url, fp, errcode, errmsg, headers)
  File "C:\Python26\lib\urllib.py", line 371, in http_error
    result = method(url, fp, errcode, errmsg, headers)
  File "C:\Python26\lib\urllib.py", line 636, in http_error_302
    data)
  File "C:\Python26\lib\urllib.py", line 651, in redirect_internal
    return self.open(newurl)
  File "C:\Python26\lib\urllib.py", line 203, in open
    return getattr(self, name)(url)
  File "C:\Python26\lib\urllib.py", line 345, in open_http
    errcode, errmsg, headers = h.getreply()
  File "C:\Python26\lib\httplib.py", line 1024, in getreply
    response = self._conn.getresponse()
  File "C:\Python26\lib\httplib.py", line 950, in getresponse
    response.begin()
  File "C:\Python26\lib\httplib.py", line 390, in begin
    version, status, reason = self._read_status()
  File "C:\Python26\lib\httplib.py", line 348, in _read_status
    line = self.fp.readline()
  File "C:\Python26\lib\socket.py", line 395, in readline
    data = recv(1)
IOError: [Errno socket error] [Errno 10054] Eine vorhandene Verbindung wurde vom Remotehost geschlossen[quote]

Die letzte zeile deutet ja eher auf ein problem mit dem Zielrechner hin, aber wie kann ich sowas in dem Skript abfangen? Ist mir irgendwie zu hoch...[/quote]

Verfasst: Donnerstag 30. April 2009, 08:46
von snafu

Code: Alles auswählen

from timeit import Timer


def measure(url, times):
    """
    Do an urlopen() with `url`, where `times` specifies how often it is done
    
    Return (total time, average time)
    """
    setup = 'from urllib import urlopen'
    cmd = 'urlopen("%s")' % url
    timer = Timer(cmd, setup)
    time = timer.timeit(number=times)
    return time, time/times


if __name__ == '__main__':
    url = 'http://www.ebay.de/'
    times = 3
    total, average = measure(url, times)
    print "Result after opening %d x %s:\n" \
          "Total: %.2f seconds\n" \
          "Average: %.2f seconds" \
          % (times, url, total, average)

Verfasst: Freitag 1. Mai 2009, 17:36
von bankkind
Danke danke.

ich habe es mal mit time probiert. Ist das Theoretisch auch richtig? Evtl. aber schlecht gelöst?

Code: Alles auswählen

start = time.clock() 
f = urllib.urlopen(url)
ende = time.clock() 
print "Die Funktion lief %2f Sekunden" % (ende - start)
Ist Grundsätzlich sinnvoll das import erst in der timeit Funktion mit durchzuführen? Bremst das nicht auch?

Code: Alles auswählen

setup = 'from urllib import urlopen'
cmd = 'urlopen("%s")' % url
timer = Timer(cmd, setup)
Ich bin etwas verwirrt über die Vielfalt ;-)

Verfasst: Freitag 1. Mai 2009, 18:02
von HerrHagen
ich habe es mal mit time probiert. Ist das Theoretisch auch richtig? Evtl. aber schlecht gelöst?
Für die Messung von Ereignissen wie du sie mit urlib vor hast, ist das vollkommen in Ordnung.
Ist Grundsätzlich sinnvoll das import erst in der timeit Funktion mit durchzuführen? Bremst das nicht auch?
Der import wird nicht mit in die Zeitmessung einbezogen, da er über den setup parameter übergeben wurde. Die Zeitmessung erfolgt nur über das was im stmt Parameter (hier cmd) steht.

MFG HerrHagen

Verfasst: Freitag 1. Mai 2009, 18:26
von Leonidas
HerrHagen hat geschrieben:
ich habe es mal mit time probiert. Ist das Theoretisch auch richtig? Evtl. aber schlecht gelöst?
Für die Messung von Ereignissen wie du sie mit urlib vor hast, ist das vollkommen in Ordnung.
Im vorleigenden Fall finde ich es sogar besser. Code in Strings ist irgendwie... *bäh*.

Verfasst: Freitag 1. Mai 2009, 18:53
von bankkind
OK, aber nun bin ich wieder bei einem anderen Problem... wie kann ich hier ein timeout einbauen? EIne Idee von mir wäre hier

Code: Alles auswählen

start = time.clock()
f = urllib.urlopen(url)
ende = time.clock()
print "Die Funktion lief %2f Sekunden" % (ende - start)
zum Beispiel so eine Art Checkpoint einzubauen, aber nur wie???

Ich würde dann diesen Checkpoint vergleichen und wenn er über einem bestimmten Wert ist, danngibt es einen TimeOut...

EDIT:

Auch noch lustig: auf meinem XP Rechner kommt ein vernünftiges Ergebnis raus:

Code: Alles auswählen

http://www.ebay.de: 0.65 Sekunden
http://www.ebay.de: 0.56 Sekunden
http://www.ebay.de: 0.54 Sekunden
http://www.ebay.de: 0.58 Sekunden
http://www.ebay.de: 0.53 Sekunden
Auf nem Linux vServer:

Code: Alles auswählen

http://www.ebay.de: 0.00 Sekunden
http://www.ebay.de: 0.00 Sekunden
http://www.ebay.de: 0.00 Sekunden
http://www.ebay.de: 0.00 Sekunden
http://www.ebay.de: 0.00 Sekunden
Ist das hier die bessere Anbindung oder einfach nur Fehlerhaft? ich hab keine erklärung...

Verfasst: Samstag 2. Mai 2009, 09:06
von snafu
Für Linux solltest du besser mit `time.time()` messen. Den Grund kannst du bspw. dem Docstring des `timeit`-Moduls entnehmen. :)

Verfasst: Samstag 2. Mai 2009, 14:26
von bankkind
Ja, da shabe ich jetzt auch schon mitbekommen, mit time.time() bekomme ich bessere Ergebnisse.

Jetzt habe ich aber neben meinem noch immer ungelöstem TimeOut, das Problem das ich MySQL nicht zum laufen bekomme in Python.

Gibt es hier ein verständliches Tutorial? Bzw. denke ich das ich schon ein Kompatibilitätsproblem habe, denn es gibt keine MySQL Libfür Python 2.6...

Verfasst: Samstag 2. Mai 2009, 15:11
von Leonidas
Wo ist das Problem, MySQLdb gegen Python 2.6 zu kompilieren?

Verfasst: Montag 4. Mai 2009, 09:16
von bankkind
Leider ist das schon ein Problem. Weil für mich, der das noch nicht gemacht hat, ist das gefrickel und mir fehlt da leider eine vernünftige Anleitung.

Verfasst: Montag 4. Mai 2009, 09:40
von Leonidas
bankkind hat geschrieben:Weil für mich, der das noch nicht gemacht hat, ist das gefrickel und mir fehlt da leider eine vernünftige Anleitung.
Dann gibt es zwei Möglichkeiten: Python 2.5 nehmen oder MySQLdb-Quellen runterladen, MySQL herunterladen (und hoffen dass die Include-Dateien dabei sind) und einen Compiler herunterladen (Visual C++ Express sollte reichen, oder MinGW. Je nach Software ist der eine oder der andere Compiler brauchbarer).

Wenn du das hast machst du im MySQLdb-Ordner ein ``python setup.py build_ext`` und korrigierst solange an den Sachen rum (fehlende Include-Dateien etc) bis es dann kompiliert. Ich kann dir da auch keine genaue Anleitung geben, weil die genauen Schritte immer etwas unterschiedlich sind, je nach Compiler und Software die man kompilieren will.

Verfasst: Montag 4. Mai 2009, 10:15
von wuf
Hallo Leonidas

In der Doku zu 'timeit'
http://docs.python.org/dev/library/timeit
sind weiter unten Beispiele vorhanden. Weisst du was beim folgenden Code-Schnippsel genau abläuft:

Code: Alles auswählen

def test():
    "Stupid test function"
    L = []
    for i in range(100):
        L.append(i)

if __name__=='__main__':
    from timeit import Timer
    t = Timer("test()", "from __main__ import test")
    print t.timeit()
Bei mir wird der Printbefehl:

Code: Alles auswählen

print t.timeit()
nie ausgeführt oder es dauert eine Ewigkeit bis dies der Fall sein wird?

Gruss wuf :wink:

Verfasst: Montag 4. Mai 2009, 10:40
von Leonidas
Doch, der wird ausgeführt, nur muss der Code erstmal 1000000 durchlaufen werden, was schon ziemlich lange dauert. Das kannst du ausprobieren indem du dem Aufruf ``number=1`` als Argument mitgibst.

Verfasst: Montag 4. Mai 2009, 10:51
von wuf
@Leonidas: Danke! Alles klar.

Eine weitere Frage:

Kann eine Zeitmessung mittels 'timeit' als genau bezeichnet werden da scheinbar mit Nanosekunden-Auflösung gemessen wird?

Gruss wuf :wink: