Извлечение файлов из zip-файла и сохранение даты mod-Python 2.7.1 в Windows 7

Я пытаюсь извлечь файлы из zip-файла с помощью Python 2.7.1 (в Windows, fyi), и каждая из моих попыток показывает извлеченные файлы с измененной датой = временем извлечения (что неверно).

import os,zipfile
outDirectory = 'C:_TEMP'
inFile = 'test.zip'
fh = open(os.path.join(outDirectory,inFile),'rb') 
z = zipfile.ZipFile(fh)
for name in z.namelist():
    z.extract(name,outDirectory)
fh.close()

Я также попытался с помощью .extractall метод, с теми же результатами.

import os,zipfile
outDirectory = 'C:_TEMP'
inFile = 'test.zip'
zFile = zipfile.ZipFile(os.path.join(outDirectory,inFile))        
zFile.extractall(outDirectory)

может кто-нибудь сказать мне, что я делаю неправильно?

Я хотел бы думать, что это возможно без необходимости postcorrect измененного времени per здесь

4 ответов


Ну, это займет немного пост-обработки, но это не так уж плохо:

import os
import zipfile
import time

outDirectory = 'C:\TEMP\'
inFile = 'test.zip'
fh = open(os.path.join(outDirectory,inFile),'rb') 
z = zipfile.ZipFile(fh)

for f in z.infolist():
    name, date_time = f.filename, f.date_time
    name = os.path.join(outDirectory, name)
    with open(name, 'wb') as outFile:
        outFile.write(z.open(f).read())
    date_time = time.mktime(date_time + (0, 0, -1))
    os.utime(name, (date_time, date_time))

ладно, может, это is что плохо.


основываясь на ответе Бера, я разработал эту версию (используя Python 2.7.11), которая также учитывает даты каталога mod.

from os import path, utime
from sys import exit
from time import mktime
from zipfile import ZipFile

def unzip(zipfile, outDirectory):
    dirs = {}

    with ZipFile(zipfile, 'r') as z:
        for f in z.infolist():
            name, date_time = f.filename, f.date_time
            name = path.join(outDirectory, name)
            z.extract(f, outDirectory)

            # still need to adjust the dt o/w item will have the current dt
            date_time = mktime(f.date_time + (0, 0, -1))

            if (path.isdir(name)):
                # changes to dir dt will have no effect right now since files are
                # being created inside of it; hold the dt and apply it later
                dirs[name] = date_time
            else:
                utime(name, (date_time, date_time))

    # done creating files, now update dir dt
    for name in dirs:
       date_time = dirs[name]
       utime(name, (date_time, date_time))

if __name__ == "__main__":

    unzip('archive.zip', 'out')

    exit(0)

поскольку каталоги изменяются по мере создания извлеченных файлов внутри них, нет смысла устанавливать их даты с помощью os.utime до завершения извлечения, поэтому эта версия кэширует имена каталогов и их временные метки до самого конца.


основываясь на ответе этана Фумана, я разработал эту версию (используя Python 2.6.6), которая немного более consise:

zf = ZipFile('archive.zip', 'r')
for zi in zf.infolist():
    zf.extract(zi)
    date_time = time.mktime(zi.date_time + (0, 0, -1))
    os.utime(zi.filename, (date_time, date_time))
zf.close()

это извлекает в текущий рабочий каталог и использует ZipFile.метод extract () для записи данных вместо создания самого файла.


основываясь на ответе Jia103, я разработал функцию (используя Python 2.7.14), которая сохраняет даты каталогов и файлов после того, как все было извлечено. Это изолирует любое уродство в функции, и вы также можете использовать zipfile.Zip-файл.extractAll () или любой метод извлечения zip, который вы хотите:

import time
import zipfile
import os

# Restores the timestamps of zipfile contents.
def RestoreTimestampsOfZipContents(zipname, extract_dir):
    for f in zipfile.ZipFile(zipname, 'r').infolist():
        # path to this extracted f-item
        fullpath = os.path.join(extract_dir, f.filename)
        # still need to adjust the dt o/w item will have the current dt
        date_time = time.mktime(f.date_time + (0, 0, -1))
        # update dt
        os.utime(fullpath, (date_time, date_time))

чтобы сохранить даты, просто вызовите эту функцию после извлечения.

вот пример из сценария, который я написал для сохранения игры zip / unzip каталоги:

        z = zipfile.ZipFile(zipname, 'r')
        print 'I have opened zipfile %s, ready to extract into %s' \
                % (zipname, gamedir)
        try: os.makedirs(gamedir)
        except: pass    # Most of the time dir already exists
        z.extractall(gamedir)
        RestoreTimestampsOfZipContents(zipname, gamedir)  #<--  USED
        print '%s zip extract done' % GameName[game]

спасибо всем за ваши предыдущие ответы!