[英]Extracting a .app from a zip file in Python, using ZipFile
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. 我正在尝试从快照中提取Chromium.app的新修订版,并且可以很好地下载该文件,但是在提取时,ZipFile要么将chrome-mac文件夹提取为一个文件,要么说目录不不存在,等等。我是python的新手,所以这些错误对我来说意义不大。 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? 有任何想法吗?
It seems you have encountered a bug in Python . 看来您在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. 您可以选择使用其中一种变通办法,或者更新至Python 2.6.5或2.7b2。
One of the workarounds suggests copying the patched zipfile.py module from the fixed Python. 解决方法之一是建议从固定的Python复制修补的zipfile.py模块 。
Best of luck! 祝你好运!
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()
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
There is another problem extracting an .app from a zip in Python (which doesn't happen with a typically zip utility). 从Python中的zip提取.app时还有另一个问题(通常zip实用程序不会发生)。 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. 由于丢失了嵌套二进制文件上的执行权限位,.app可能会停止以这种方式进行后期提取。 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 (ie within the WORK_DIR
). 我的程序已经知道可以在哪里找到APP_PATH
(即在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
. 我将zip命名为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. 我很简单地在这里解析BIN_PATH
,而无需知道.app内部的二进制名称,因为我知道在我的用例中只有一个文件。 I grant full (777) permissions to it, because I simply delete the .app at the end of my script anyway. 我授予它全部(777)权限,因为无论如何我只是在脚本末尾删除.app。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.