2

I'm trying to extract new revisions of Chromium.app from their snapshots, and I can download the file fine, but when it comes to extracting it, ZipFile either extracts the chrome-mac folder within as a file, says that directories don't exist, etc. I am very new to python, so these errors make little sense to me. Here is what I have so far.

import urllib2
response = urllib2.urlopen('http://build.chromium.org/buildbot/snapshots/chromium-rel-mac/LATEST')
latestRev = response.read()
print latestRev

# we have the revision, now we need to download the zip and extract it
latestZip = urllib2.urlopen('http://build.chromium.org/buildbot/snapshots/chromium-rel-mac/%i/chrome-mac.zip' % (int(latestRev)), '~/Desktop/ChromiumUpdate/%i-update' % (int(latestRev)))
#declare some vars that hold paths n shit
workingDir = '/Users/slehan/Desktop/ChromiumUpdate/'
chromiumZipPath = '%s%i-update.zip' % (workingDir, (int(latestRev)))
chromiumAppPath = 'chrome-mac/' #the path of the chromium executable within the zip file
chromiumAppExtracted = '%s/Chromium.app' % (workingDir) # path of the extracted executable

output = open(chromiumZipPath, 'w') #delete any current file there
output.write(latestZip.read())
output.close()

# we have the .zip now we need to extract the Chromium.app file, it's in ziproot/chrome-mac/Chromium.app
import zipfile, os
zippedFile = open(chromiumZipPath)
zippedChromium = zipfile.ZipFile(zippedFile, 'r')
zippedChromium.extract(chromiumAppPath, workingDir)
#print zippedChromium.namelist()

zippedChromium.close()
#zippedChromium.close()

Any ideas?

Dharman
  • 30,962
  • 25
  • 85
  • 135
skylerl
  • 4,030
  • 12
  • 41
  • 60

4 Answers4

4

It seems you have encountered a bug in Python. This other question details the problem and workarounds. You can elect to use one of those workarounds, or update to Python 2.6.5 or 2.7b2.

One of the workarounds suggests copying the patched zipfile.py module from the fixed Python.

Best of luck!

Community
  • 1
  • 1
Jason R. Coombs
  • 41,115
  • 10
  • 83
  • 93
  • Well butter my ass and call me Susan, I upgraded and it works now. Thanks alot! – skylerl May 29 '10 at 14:38
  • Hi @skylerl and Jason R. Coombs i have added the zipfile in my exe i want to extract the zipfile wherever i run the exe can you help me with that – Joyson Jun 21 '18 at 15:00
  • i have done it using the `pyinstaller -F --add-data "installation.zip;installation.zip" phpfilescopy_extract.py --console --onefile` i need zip this exe to be like downloadable – Joyson Jun 21 '18 at 15:06
0

This seems to be working for me:

import os
import urllib2
import zipfile
from StringIO import StringIO

response = urllib2.urlopen('http://build.chromium.org/buildbot/snapshots/chromium-rel-mac/LATEST')
latestRev = response.read()
print 'getting revision', latestRev

# we have the revision, now we need to download the zip and extract it
locRef='http://build.chromium.org/buildbot/snapshots/chromium-rel-mac/%i/chrome-mac.zip' % (int(latestRev))
latestZip = StringIO(urllib2.urlopen(locRef).read())

# we have the .zip now we need to extract the Chromium.app file, it's in chrome-mac/Chromium.app/
zippedChromium = zipfile.ZipFile(latestZip)
# find all zip members in chrome-mac/Chromium.app
members = [m for m in zippedChromium.namelist() if m.startswith('chrome-mac/Chromium.app/')]
#zippedChromium.extract(chromiumAppPath, workingDir)
target = 'chromium-%s' % latestRev
if os.path.isdir(target):
    print 'destination already exists, exiting'
    raise SystemExit(1)
os.makedirs(target)
zippedChromium.extractall(target, members)

#zippedChromium.close()
Jason R. Coombs
  • 41,115
  • 10
  • 83
  • 93
  • When I run that, it returns: destination already exists, exiting – skylerl May 28 '10 at 11:31
  • I commented out the raise SystemExit(1) and it makes the directory, but when it extracts the .app, it doesn't get the whole thing, just the file itself. With .apps there is a folder within called Contents, which was not downloaded at all. – skylerl May 28 '10 at 13:28
  • Instead of commenting out SystemExit, remove chromium-NNNNN before running the script. When you run the script, it will create the directory chromium-NNNNN and extract chrome-mac/Chromium.app/* to chromium-NNNNN. – Jason R. Coombs May 28 '10 at 14:20
  • Okay, I deleted the folder, and now it says: getting revision 48479 IOError: [Errno 20] Not a directory: 'chromium-48479/chrome-mac/Chromium.app/Contents' – skylerl May 28 '10 at 14:36
  • Is the line os.makedirs(target) still present? That line makes sure the 'target' directory exists before running the extractall method. – Jason R. Coombs May 28 '10 at 14:49
  • Yeah it still exists. I figure you're on Unix right? Maybe Mac OS responds to the .app differently than Mac OS X. – skylerl May 28 '10 at 15:18
  • I'm beginning to think you have a buggy zipfile lib. What OS and Python version are you using? I'm using Windows 7 64-bit with Python 2.6.5 64-bit. – Jason R. Coombs May 28 '10 at 17:41
  • Python 2.6.1 (r261:67515, Feb 11 2010, 00:51:29) [GCC 4.2.1 (Apple Inc. build 5646)] on darwin – skylerl May 29 '10 at 01:19
0

Here's another cut - this is the same technique, but it walks the result to demonstrate that it works.

import os
import urllib2
import zipfile
from StringIO import StringIO

response = urllib2.urlopen('http://build.chromium.org/buildbot/snapshots/chromium-rel-mac/LATEST')
latestRev = response.read()
print 'getting revision', latestRev

# we have the revision, now we need to download the zip and extract it
locRef='http://build.chromium.org/buildbot/snapshots/chromium-rel-mac/%i/chrome-mac.zip' % (int(latestRev))
latestZip = StringIO(urllib2.urlopen(locRef).read())

# we have the .zip now we need to extract the Chromium.app file, it's in chrome-mac/Chromium.app/
zippedChromium = zipfile.ZipFile(latestZip)
# find all zip members in chrome-mac/Chromium.app
members = [m for m in zippedChromium.namelist() if m.startswith('chrome-mac/Chromium.app/')]
#zippedChromium.extract(chromiumAppPath, workingDir)
target = 'chromium-%s' % latestRev
if os.path.isdir(target):
    print 'destination already exists, exiting'
    raise SystemExit(1)
os.makedirs(target)
zippedChromium.extractall(target, members)

lengths = [
    (len(dirnames), len(filenames))
    for dirpath, dirnames, filenames in os.walk(target)
    ]
dirlengths, filelengths = zip(*lengths)
ndirs = sum(dirlengths)
nfiles = sum(filelengths)
print 'extracted %(nfiles)d files in %(ndirs)d dirs' % vars()
#zippedChromium.close()

The output I get when I run it is

> .\getapp.py
getting revision 48479
extracted 537 files in 184 dirs
Jason R. Coombs
  • 41,115
  • 10
  • 83
  • 93
  • Same thing =( IOError: [Errno 20] Not a directory: 'chromium-48479/chrome-mac/Chromium.app/Contents' – skylerl May 28 '10 at 15:19
0

There is another problem extracting an .app from a zip in Python (which doesn't happen with a typically zip utility). No one else seems to have mentioned this...

The .app can ceases to function post extraction this way, as a result of losing the execution permission bit on the nested binary. You can fix this though, by simply granting that again.

Here's a loose snippet of code that I'm using. Revise this as needed for your purposes (or write a more generic function to handle this situation in a more universal manner):

import os, zipfile
...
ZIP_PATH     = APP_PATH + ".zip" 
APP_BIN_DIR  = os.path.join( APP_PATH, "Contents/MacOS" )
zipfile.ZipFile( ZIP_PATH, 'r' ).extractall( WORK_DIR )   
BIN_PATH = os.path.join( APP_BIN_DIR, os.listdir( APP_BIN_DIR )[0] )
os.chmod( BIN_PATH, 0o777 )

My program already knew where to expect the APP_PATH to be found (i.e. within the WORK_DIR). I had to zip it up though, and shoe horn that detail in after the fact. I name my zip like XXXXX.app.zip. I resolve the BIN_PATH here pretty simply without the need to know the name of binary inside the .app, because I know there is only going to be one file in there for my use case. I grant full (777) permissions to it, because I simply delete the .app at the end of my script anyway.

BuvinJ
  • 10,221
  • 5
  • 83
  • 96