[Python-de] urllib2 und tarfile

Christian Heimes christian at python.org
Mo Mär 11 15:03:35 CET 2013


Am 11.03.2013 14:40, schrieb Olе Streicher:
> Hallo,
> 
> ich möchte gerne ein Tar-file mittels http herunterladen und on the fly
> extrahieren (python 2.7). Passend erschien mir urllib2 und tarfile:
> 
> ---------------------8<-------------------------------
> import urllib2
> import tarfile
> 
> url = "http://ftp.gnu.org/gnu/hello/hello-2.8.tar.gz"
> tar = tarfile.open(fileobj = urllib2.urlopen(url))
> tar.extractall()
> ---------------------8<-------------------------------
> 
> Das liefert ein
> 
> Traceback (most recent call last):
>   File "<stdin>", line 5, in <module>
>   File "/usr/lib64/python2.7/tarfile.py", line 1656, in open
>     saved_pos = fileobj.tell()
> AttributeError: addinfourl instance has no attribute 'tell'
> 
> Die Dokumentation zu urllib2.urlopen sagt allerdings:
> 
> | This function returns a file-like object with two additional methods:
> |
> |    geturl() — return the URL of the resource retrieved, commonly used
> |        to determine if a redirect was followed 
> |    info() — return the meta-information of the page, such as headers,
> |        in the form of an mimetools.Message instance (see Quick Reference
> |        to HTTP Headers) 
> |    getcode() — return the HTTP status code of the response.
> 
> Abgesehen davon, dass der Autor nicht zählen konnte: irgendwie passt
> die Dokumentation nicht zur Exception, oder habe ich hier einen
> Denkfehler?

Das Problem ist, dass das Objekt nur Datei-ähnlich ist und keine Datei
ist. Sockets sind grundsätzlich nicht seek-able, da es sich um streams
handelt und nicht im Block-IO. Darum implementieren die Objekte kein
tell() und seek().

Das TAR-Module kann auch mit Streams umgehen, wenn man den richtigen
Modus verwendet:

import urllib2
import tarfile
url = "http://ftp.gnu.org/gnu/hello/hello-2.8.tar.gz"
response = urllib2.urlopen(url)
tar = tarfile.open(fileobj=response, mode = "r|*")
tar.extractall()

Von http://docs.python.org/2.7/library/tarfile.html#tarfile.open

  For special purposes, there is a second format for mode:
  'filemode|[compression]' ...  Use this variant in combination
  with e.g. sys.stdin, a socket file object or a tape device.

Christian



Mehr Informationen über die Mailingliste python-de