38

I'm trying to extract a specific file from a zip archive using python.

In this case, extract an apk's icon from the apk itself.

I am currently using

with zipfile.ZipFile('/path/to/my_file.apk') as z:
    # extract /res/drawable/icon.png from apk to /temp/...
    z.extract('/res/drawable/icon.png', 'temp/')

which does work, in my script directory it's creating temp/res/drawable/icon.png which is temp plus the same path as the file is inside the apk.

What I actually want is to end up with temp/icon.png.

Is there any way of doing this directly with a zip command, or do I need to extract, then move the file, then remove the directories manually?

ivanleoncz
  • 9,070
  • 7
  • 57
  • 49
rcbevans
  • 7,101
  • 4
  • 30
  • 46

1 Answers1

59

You can use zipfile.ZipFile.open:

import shutil
import zipfile

with zipfile.ZipFile('/path/to/my_file.apk') as z:
    with z.open('/res/drawable/icon.png') as zf, open('temp/icon.png', 'wb') as f:
        shutil.copyfileobj(zf, f)

Or use zipfile.ZipFile.read:

import zipfile

with zipfile.ZipFile('/path/to/my_file.apk') as z:
    with open('temp/icon.png', 'wb') as f:
        f.write(z.read('/res/drawable/icon.png'))
ivanleoncz
  • 9,070
  • 7
  • 57
  • 49
falsetru
  • 357,413
  • 63
  • 732
  • 636
  • Both very nice answers, far more eloquent than just moving it like I was. Minor correction to fit question asked, is with open(os.path.join(tDir,os.path.basename(icon[1])), 'wb') as f: so that the output icon is in the temp dir, not cwd() where script is. Thanks – rcbevans Jul 18 '13 at 17:37
  • 1
    It's worth noting that the CPython implementations of `extract` and `extract_all` use the "`zipfile.ZipFile.open`" version: e.g. https://github.com/python/cpython/blob/v3.7.0/Lib/zipfile.py#L1647 – Nzbuu Aug 17 '18 at 12:34
  • 1
    You're welcome @falsetru . I tried your implementation and I noticed some problems, that I realized that was the lack of the import. Besides this, it works like a clockwork. – ivanleoncz Sep 10 '20 at 14:51
  • 2
    Be aware that using `zipfile.ZipFile.read` will load the full file in memory before writing it to the disk. – darkheir Jun 09 '21 at 08:27