18

I would like to download a zip file from internet and extract it.

I would rather use requests. I don't want to write to the disk.

I knew how to do that in Python2 but I am clueless for python3.3. Apparently, zipfile.Zipfile wants a file-like object but I don't know how to get that from what requests returns.

If you know how to do it with urllib.request, I would be curious to see how you do it too.

Asclepius
  • 57,944
  • 17
  • 167
  • 143
user1720740
  • 848
  • 1
  • 7
  • 17

3 Answers3

41

I found out how to do it:

request = requests.get(url)
file = zipfile.ZipFile(BytesIO(request.content))

What I was missing :

  • request.content should be used to access the bytes
  • io.BytesIO is the correct file-like object for bytes.
Asclepius
  • 57,944
  • 17
  • 167
  • 143
user1720740
  • 848
  • 1
  • 7
  • 17
8

Here's another approach saving you having to install requests:

    r = urllib.request.urlopen(req)
    with zipfile.ZipFile(BytesIO(r.read())) as z:
        print( z.namelist() )
Baz
  • 12,713
  • 38
  • 145
  • 268
  • 3
    I'll give you an upvote so at least it's not < 0, I think it's a good answer, although I prefer using requests :) – zapatilla Mar 15 '16 at 10:54
  • I like this answer - it avoids requiring to install `requests` library for simple use-cases, e.g. downloading asset file from GitHub release. – Bojan P. Apr 26 '23 at 20:11
6

Using Requests, this can be done very simply.

import requests, zipfile, StringIO
response = requests.get(zip_file_url)
zipDocument = zipfile.ZipFile(StringIO.StringIO(response.content))

Using String.IO you can make a file-like object for the responses content attribute.

If you want to extract to directory you can use the ZipFile's extractall() function

zipDocment.extractall()
Qrtn
  • 794
  • 6
  • 17
aonbyte
  • 376
  • 1
  • 2
  • 10
  • There is no StringIO.StringIO in Python3. One could use io.StringIO. That fails miserably on my installation. Maybe there is something wrong with my installation : TypeError: initial_value must be str or None, not bytes – user1720740 May 02 '14 at 08:23
  • 2
    -1, this doesn't work in Python 3 - StringIO takes a str while both `ZipFile` and `response.content` require bytes. `io.ByteIO` is the thing to use – dbr Oct 27 '14 at 10:53
  • There are typos in the answer and the comment by @dbr: Should be `zipDocument.extractall()` and `io.BytesIO`. I.e., `zipfile.ZipFile(io.BytesIO(response.content))` (_note: cannot edit the answer_) – Michal Skop May 04 '17 at 11:31