简体   繁体   English

使用ZipFile从Python的zip文件中提取.app

[英]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.

相关问题 在Python中从zip文件中提取.app - Extracting .app from zip file in Python 使用带有--py文件的.zip文件(使用zipfile包在python中创建)导入模块时出现问题 - Problem importing modules from a .zip file (created in python using zipfile package) with --py-files on an EMR in Spark 使用Python zipfile从ZIP中提取文件名中包含特定字符串的文件 - Extract file that contains specific string on filename from ZIP using Python zipfile 是否可以使用 python zipfile 库仅下载 ZIP 文件的一部分 - Is it possible to download just part of a ZIP file using python zipfile library 使用 Zipfile 模块 python 重命名写入 zip 文件的文件 - Rename files written to zip file using Zipfile module python 使用zipfile模块在python中创建具有压缩功能的zip文件 - Creating a zip file with compression in python using the zipfile module 使用Python zipfile模块删除zip文件中的文件夹 - Deleting a folder in a zip file using the Python zipfile module Python zipfile从zip文件内的目录中提取文件 - Python zipfile extract files from directory inside a zip file 使用python ZipFile从zip中提取文件而不保留结构? - Extract files from zip without keeping the structure using python ZipFile? python zipfile.ZipFile() 方法从 6M 原始文件生成 20G zip 文件 - python zipfile.ZipFile() method generates 20G zip file from 6M original
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM