Извлечение .app из zip-файла в Python с использованием ZipFile

Я пытаюсь извлечь новые версии 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()

Любые идеи?


person skylerl    schedule 28.05.2010    source источник


Ответы (4)


Похоже, вы столкнулись с ошибкой в ​​Python. Этот другой вопрос подробно описывает проблему и обходные пути. Вы можете использовать один из этих обходных путей или обновиться до Python 2.6.5 или 2.7b2.

Один из обходных путей предлагает скопировать исправленный модуль zipfile.py. из исправленного Python.

Удачи!

person Jason R. Coombs    schedule 29.05.2010
comment
Что ж, смажьте меня задницей и зовите меня Сьюзен, я обновился, и теперь это работает. Большое спасибо! - person skylerl; 29.05.2010
comment
Привет @skylerl и Джейсон Р. Кумбс, я добавил zip-файл в свой exe-файл, я хочу извлечь zip-файл, где бы я ни запускал exe, вы можете помочь мне с этим. - person Joyson; 21.06.2018
comment
я сделал это, используя pyinstaller -F --add-data "installation.zip;installation.zip" phpfilescopy_extract.py --console --onefile, мне нужно заархивировать этот exe, чтобы его можно было загрузить - person Joyson; 21.06.2018

Кажется, это работает для меня:

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()
person Jason R. Coombs    schedule 28.05.2010
comment
Когда я запускаю это, он возвращает: пункт назначения уже существует, выход - person skylerl; 28.05.2010
comment
Я закомментировал повышение SystemExit(1), и он создает каталог, но когда он извлекает .app, он получает не все, а только сам файл. В .apps есть папка Contents, которая вообще не загружалась. - person skylerl; 28.05.2010
comment
Вместо комментирования SystemExit удалите chromium-NNNNN перед запуском скрипта. Когда вы запустите скрипт, он создаст каталог chromium-NNNNN и извлечет chrome-mac/Chromium.app/* в chromium-NNNNN. - person Jason R. Coombs; 28.05.2010
comment
Хорошо, я удалил папку, и теперь она говорит: получение версии 48479 IOError: [Errno 20] Не каталог: 'chromium-48479/chrome-mac/Chromium.app/Contents' - person skylerl; 28.05.2010
comment
Строка os.makedirs(target) все еще присутствует? Эта строка проверяет существование целевого каталога перед запуском метода extractall. - person Jason R. Coombs; 28.05.2010
comment
Да он до сих пор существует. Я полагаю, вы используете Unix, верно? Возможно, Mac OS реагирует на .app иначе, чем Mac OS X. - person skylerl; 28.05.2010
comment
Я начинаю думать, что у вас глючная библиотека zipfile. Какую версию ОС и Python вы используете? Я использую 64-разрядную версию Windows 7 с 64-разрядной версией Python 2.6.5. - person Jason R. Coombs; 28.05.2010
comment
Python 2.6.1 (r261:67515, 11 февраля 2010 г., 00:51:29) [GCC 4.2.1 (Apple Inc., сборка 5646)] на Darwin - person skylerl; 29.05.2010

Вот еще один разрез — это тот же метод, но он показывает результат, чтобы продемонстрировать, что он работает.

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
person Jason R. Coombs    schedule 28.05.2010
comment
То же самое =( IOError: [Errno 20] Не каталог: 'chromium-48479/chrome-mac/Chromium.app/Contents' - person skylerl; 28.05.2010

Существует еще одна проблема с извлечением .app из zip-архива в Python (чего не происходит с обычной zip-утилитой). Кажется, об этом еще никто не упоминал...

.app может перестать функционировать после извлечения таким образом в результате потери бита разрешения на выполнение во вложенном двоичном файле. Однако вы можете исправить это, просто предоставив это снова.

Вот свободный фрагмент кода, который я использую. Измените это по мере необходимости для ваших целей (или напишите более общую функцию, чтобы справиться с этой ситуацией более универсальным образом):

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). Однако мне пришлось застегнуть его на молнию и обуть эту деталь постфактум. Я называю свой почтовый индекс как XXXXX.app.zip. Я разрешаю BIN_PATH здесь довольно просто, без необходимости знать имя двоичного файла внутри .app, потому что я знаю, что там будет только один файл для моего варианта использования. Я даю ему полные (777) разрешения, потому что я все равно просто удаляю .app в конце моего скрипта.

person BuvinJ    schedule 17.03.2019