18.10.2013 Aufrufe

PDF-Version - freiesMagazin

PDF-Version - freiesMagazin

PDF-Version - freiesMagazin

MEHR ANZEIGEN
WENIGER ANZEIGEN

Sie wollen auch ein ePaper? Erhöhen Sie die Reichweite Ihrer Titel.

YUMPU macht aus Druck-PDFs automatisch weboptimierte ePaper, die Google liebt.

Python – Teil 10: Kurzer Prozess von Daniel Nögel<br />

Im letzten Teil der Python-Reihe (siehe<br />

<strong>freiesMagazin</strong> 10/2011 [1]) wurde die<br />

urllib-Bibliothek vorgestellt und damit<br />

ein Client für den FileHoster BayFiles.com<br />

implementiert. In diesem Teil soll<br />

das subprocess-Modul vorgestellt werden,<br />

mit dem sich Prozesse starten, Rückgabewerte<br />

auslesen und Pipes umsetzen lassen.<br />

Besprechung der Übung<br />

Zunächst soll aber die im letzten Teil vorgeschlagene<br />

Aufgabe besprochen werden. Umgesetzt<br />

werden sollte eine Download-Funktion mit Fortschrittsanzeige,<br />

die es auch erlaubt, begonnene<br />

Downloads fortzusetzen.<br />

Eine fertige Beispiellösung findet sich bei<br />

GitHub [2]. Einige Besonderheiten sollen im Folgenden<br />

besprochen werden.<br />

In Zeile 12 wird die Zieldatei im Modus ab geöffnet.<br />

Dies bedeutet, dass die Datei binär geöffnet<br />

wird und neue Daten angehängt werden<br />

(append). Wenn die Zieldatei bereits vorhanden<br />

war (resume in Zeile 11 also den Wert True zugewiesen<br />

bekommen hat), wird in Zeile 15/16 zunächst<br />

die aktuelle Dateigröße ermittelt. Dies wäre<br />

auch mit der Funktion os.path.getsize möglich,<br />

da die Datei hier aber bereits geöffnet vorliegt,<br />

wird mit dem Aufruf fh.seek(0, 2) die Position<br />

auf Byte 0 relativ zum Ende der Datei gesetzt<br />

und die Position (und damit die Größe) mit<br />

fh.tell() ermittelt.<br />

Diese Größenangabe wird in den Zeilen 17/18<br />

genutzt, um einen HTTP-Request zu erzeugen,<br />

der die restliche Datei vom Server anfordert.<br />

Der entsprechende Eintrag im HTTP-Header<br />

lautet dann beispielsweise Range: bytes=100-.<br />

Wenn der Fehler 416 geworfen wird, bedeutet<br />

dies, dass die lokale Datei bereits vollständig ist<br />

und der Server keine weiteren Daten bereit hält.<br />

In diesem Fall gilt der Download als abgeschlossen<br />

(Zeilen 22-25).<br />

In den Zeilen 27-34 wird zunächst die Gesamtlänge<br />

des Downloads ermittelt. Durch die Verwendung<br />

des Range-Headers liefert der Server<br />

auf die Frage nach Content-Length allerdings<br />

lediglich die Restgröße des Downloads zurück,<br />

sodass die Größe der bereits heruntergeladenen<br />

Daten hinzuaddiert werden muss (Zeile 28). Tritt<br />

hierbei ein Fehler auf, wird die Größe pauschal<br />

auf 999999999 Bytes festgelegt. Eine Lösung,<br />

die hier auf Grund der Kürze gewählt wurde.<br />

Schöner wäre es beispielsweise, in diesen Fällen<br />

die Größe auf -1 zu setzen und weiter unten im<br />

Code statt einer Fortschrittsanzeige die Meldung<br />

„Gesamtgröße konnte nicht ermittelt werden“ anzuzeigen.<br />

Der Code-Block in den Zeilen 35-41 wird ausgeführt,<br />

wenn die Zieldatei noch nicht vorhanden<br />

war. Auch hier wird die Download-Größe ermittelt<br />

und im Fehlerfall auf 999999999 gesetzt.<br />

In den Zeilen 43-49 findet der eigentliche Download<br />

statt. Der Ausdruck while content ist so<br />

PROGRAMMIERUNG<br />

lange wahr, wie der Aufruf wh.read(blocksize)<br />

in den Zeilen 43 und 46 Daten vom Server zurückliefert<br />

und an den Namen content bindet.<br />

Die gelesenen Daten werden mit einem Zähler<br />

hochgezählt (Zeile 45) und in die Zieldatei geschrieben<br />

(Zeile 46). In den Zeilen 47 und 48 wird<br />

schließlich – wie schon im letzten Teil dieser Einführung<br />

– eine sehr einfache Fortschrittsanzeige<br />

umgesetzt.<br />

Da nicht jeder Server die Anfrage Content-<br />

Length unterstützt und auch nicht jeder Server<br />

den Range-Header berücksichtigt, bietet dieses<br />

Vorgehen insgesamt durchaus Spielraum für<br />

Fehler und Probleme. Dennoch wird durch das<br />

Skript veranschaulicht, wie man einen derartigen<br />

HTTP-Download mit Fortsetzen-Funktion prinzipiell<br />

umsetzen würde.<br />

subprocess<br />

Das subprocess-Modul [3] ist ein recht mächtiges<br />

Werkzeug rund um das Erzeugen von Prozessen.<br />

Damit lassen sich nicht nur Prozesse<br />

ausführen, sondern auch Rückgabewerte und<br />

Fehler auslesen, Eingaben senden und Pipes erzeugen.<br />

Es stellt damit eine wichtige Alternative<br />

zu der Funktion os.system dar, die von Anfängern<br />

gerne genutzt wird, von der aber sogar in<br />

der offiziellen Python-Dokumentation abgeraten<br />

wird [4].<br />

Statt also beispielsweise einen neuen Tab im<br />

Firefox auf diese Weise zu öffnen<br />

© <strong>freiesMagazin</strong> CC-BY-SA 3.0 Ausgabe 12/2011 40

Hurra! Ihre Datei wurde hochgeladen und ist bereit für die Veröffentlichung.

Erfolgreich gespeichert!

Leider ist etwas schief gelaufen!