【问题标题】:Extracting a .app from a zip file in Python, using ZipFile使用 ZipFile 从 Python 中的 zip 文件中提取 .app
【发布时间】:2010-05-28 10:58:37
【问题描述】:

我正在尝试从他们的快照中提取 Chromium.app 的新修订版,我可以很好地下载该文件,但是在提取它时,ZipFile 要么将 chrome-mac 文件夹提取为一个文件,而是说目录不存在,等等。我对 python 很陌生,所以这些错误对我来说意义不大。这是我目前所拥有的。

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()

有什么想法吗?

【问题讨论】:

    标签: python extract partial zipfile


    【解决方案1】:

    您似乎遇到了bug in Python。这个other question 详细说明了问题和解决方法。您可以选择使用其中一种解决方法,或更新到 Python 2.6.5 或 2.7b2。

    其中一种解决方法建议从固定的 Python 复制 patched zipfile.py module

    祝你好运!

    【讨论】:

    • 好吧,给我打个屁,叫我苏珊,我升级了,现在可以了。非常感谢!
    • 嗨 @skylerl 和 Jason R. Coombs 我已经在我的 exe 中添加了 zipfile 我想在我运行 exe 的任何地方提取 zipfile 你能帮我吗
    • 我已经使用pyinstaller -F --add-data "installation.zip;installation.zip" phpfilescopy_extract.py --console --onefile 完成了它,我需要压缩这个 exe 才能像下载一样
    【解决方案2】:

    这似乎对我有用:

    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()
    

    【讨论】:

    • 当我运行它时,它返回:目的地已经存在,正在退出
    • 我注释掉了 raise SystemExit(1) 并且它创建了目录,但是当它提取 .app 时,它并没有得到整个东西,只是文件本身。 .apps 中有一个名为 Contents 的文件夹,根本没有下载。
    • 不要注释掉 SystemExit,而是在运行脚本之前删除 chromium-NNNNN。运行脚本时,它将创建 chromium-NNNNN 目录并将 chrome-mac/Chromium.app/* 提取到 chromium-NNNNN。
    • 好的,我删除了文件夹,现在它显示:getting revision 48479 IOError: [Errno 20] Not a directory: 'chromium-48479/chrome-mac/Chromium.app/Contents'跨度>
    • os.makedirs(target) 行是否仍然存在?该行确保在运行 extractall 方法之前存在“目标”目录。
    【解决方案3】:

    这是另一个剪辑 - 这是相同的技术,但它会遍历结果以证明它有效。

    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()
    

    我运行它时得到的输出是

    > .\getapp.py
    getting revision 48479
    extracted 537 files in 184 dirs
    

    【讨论】:

    • 同样的事情 =( IOError: [Errno 20] Not a directory: 'chromium-48479/chrome-mac/Chromium.app/Contents'
    【解决方案4】:

    在 Python 中从 zip 中提取 .app 存在另一个问题(通常的 zip 实用程序不会发生这种情况)。似乎没有其他人提到过这个......

    由于丢失了嵌套二进制文件上的执行权限位,.app 可以停止以这种方式进行后提取。不过,您可以通过再次授予该权限来解决此问题。

    这是我正在使用的一个松散的 sn-p 代码。根据您的需要修改此内容(或编写更通用的函数以更通用的方式处理这种情况):

    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 )
    

    我的程序已经知道在哪里可以找到APP_PATH(即在WORK_DIR 内)。不过,我不得不把它拉上拉链,然后在事后把那个细节塞进去。我将我的 zip 命名为 XXXXX.app.zip。我在这里很简单地解决了BIN_PATH,而无需知道.app 中二进制文件的名称,因为我知道我的用例中只有一个文件。我授予它完全 (777) 权限,因为无论如何我只是删除了脚本末尾的 .app 。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-06-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-09-20
      相关资源
      最近更新 更多