Python ist in seinen Grundeigenschaften eine Programmiersprache, die gut dazu geeignet ist schnell und elegant Aufgaben aller Art zu erledigen.
Von der Systemadministration über wissenschaftliches Arbeiten bis hin zur Webentwicklung ist alles problemlos mit Python möglich. Zusammen mit der umfangreichen Standardbibliothek und einer großen Anzahl von third party Modulen hat der Pythonista alles Nötige beisammen, um die typischen Aufgaben zu stemmen.
Da ich Python hauptsächlich dazu verwende um Plugins für das Monitoring-Werkzeug Nagios zu schreiben und dabei vor allem mit Webservern über HTTP kommuniziere, nutze ich in der Regel die urllib für diese Aufgabe. Die urllib ist in der Python Standardbibliothek enthalten und liefert mit urllib.urlopen() im Grunde alles um mit URLs umzugehen.
Warum jetzt aber ein weiteres Modul? Die Antwort ist denkbar einfach: Im modernen Web nutzt man nicht nur URLs alleine, sondern man muss sich darüber hinaus auch noch um um viele Details rund um die Kommunikation kümmern. Gerade die Authentifizierung gegenüber modernen REST Schnittstellen und die steigende Bedeutung von GET, POST, PUT, DELETE und HEAD im vielzitierten “Mitmach-Web” ist eine Aufgabe bei der bei Nutzung der urllib mehr Code nötig ist, als der typische Python-Entwickler von seiner API erwartet. Gerade wenn es um das Debuggen komplexer Vorgänge an REST-Schnittstellen geht ist weniger deshalb häufig mehr. Wer beispielsweise ein Modul für die Zahlungsabwicklung zwischen einem Webshop und einem – oder mehreren – Zahlungsdienstleistern implementiert freut sich über schlanken Quellcode und eine intuitive API im Sinne des PEP 20 oder schöner: “The Zen of Python”.
Kenneth Reitz hatte wohl das PEP 20 im Hinterkopf, als er auf Basis der urllib mit seinem requests-Modul eine Alternative geschaffen hat, die 90% der typischen Anwendungsfälle eines Webentwicklers abdeckt und gleichzeitig deutlich intuitiver zu handhaben ist.
Ein Beispiel in der die urllib mit Kenneth’s requests Modul verglichen wird gibt der Autor selbst. Der Beispielcode zeigt sehr schön das simple API-Design von Kenneth. Das häufig verwendete GET wurde direkt als Methode abgebildet und die bei Webservices obligatorische Authentifizierung ist als (optionaler) Parameter realisiert. Der Statuscode eines GET-Abrufs wird als einfacher Integer verfügbar gemacht und der beim GET-Request verwendete URL als String hinterlegt. Die gelieferten Header werden dagegen in ein handliches Dictionary gefüllt. Alles ganz so wie man es intuitiv erwarten würde.
Ein Beispielabruf anhand der populärsten HTTP-Methode (die Inhalte der einzelnen Felder stehen in Kommentarzeichen)
import requests
import pprint
r = requests.get("http://www.nytimes.com/")
r.status_code
# 200
r.cookies
# {'RMID': '32356e0019a84e6a16fb23b7', 'adxcs': 's*27d12=0:1|s*2550c=0:1|s*25056=0:1'}
pprint.pprint(r.headers)
#{'cache-control': 'no-cache',
# 'content-encoding': 'gzip',
# 'content-type': 'text/html; charset=UTF-8',
# 'date': 'Fri, 09 Sep 2011 13:39:07 GMT',
# 'expires': 'Thu, 01 Dec 1994 16:00:00 GMT',
# 'pragma': 'no-cache',
# 'server': 'Sun-ONE-Web-Server/6.1',
# 'set-cookie': 'RMID=32356e0019a84e6a16fb23b7; expires=Saturday, 08-Sep-2012 13:39:07 GMT; path=/; domain=.nytimes.com, adxcs=-; path=/; domain=.nytimes.com, adxcs=s*27d12=0:1|s*2550c=0:1|s*25056=0:1; path=/; domain=.nytimes.com',
# 'transfer-encoding': 'chunked'}
r.url
# 'http://www.nytimes.com/'
Analog zur GET-Methode funktionieren natürlich auch die anderen HTTP-Methoden, die das requests-Modul unterstützt.
Natürlich hat dieser 90% Ansatz von Kenneth Reitz auch seine Nachteile.
In den fehlenden 10% steckt beispielsweise die Möglichkeit Proxies zu verwenden, was man mit der urllib folgendermaßen notieren würde: (diese Information ist mittlerweile nicht mehr korrekt. Siehe Update am Ende dieses Artikels).
import urllib
proxies = {'http': 'http://proxy.example.com:8080/'}
opener = urllib.FancyURLopener(proxies)
f = opener.open("http://www.python.org")
f.read()
Da das requests-Modul noch nicht einmal seinen einjährigen Geburtstag gefeiert hat, ist davon auszugehen, dass sich in den nächsten Monaten hier noch einiges tun wird und aus der 90% Lösung vielleicht irgendwann die 99% Lösung wird. Zwingend nötig ist das allerdings nicht, denn das gesetzte Ziel über die urllib einen leichtgewichtigen Wrapper zu stülpen, der die urllib für viele erst sinnvoll benutzbar macht, hat Kenneth Reitz schon erreicht.
Update:
Mittlerweile unterstützt das requests Modul Proxies, wie man in der Dokumentation bei “Proxies” unter “Advanced Usage” nachlesen kann.