2

Нужно проверить наличие файла и поместить его в архив. Известен путь до файла. Неизвестно, существует этот путь или нет.

Мне нужно, чтобы выполнялось условие: если файл существует по указанному пути то архивировать; если нет, то пропустить.

Я мог бы и напрямую, но моя программа завершается на половине из-за ошибки нахождения файла. Мне нужно добавить в нее подобное условие.

3 Answers3

2

Чтобы добавить файл в архив, если файл существует и пропустить его в противном случае:

from zipfile import ZipFile

with ZipFile(archive_path, 'a') as archive:
    for filename in filenames:
        try:
            archive.write(filename)
        except FileNotFoundError:
            pass # ignore non-existing files
jfs
  • 52,361
1

Я предлагаю использовать функцию os.path.isfile, чтобы проверить правильность файла для архивации.

Функция os.path.isfile возвращает true, только если путь ведёт к файлу и этот файл существует.

import os
import gzip

def process_file(filename):
    if not os.path.isfile(filename):
        return
    with gzip.open(filename + '.gz', 'wb') as archive, open(filename, 'rb') as f:
        archive.write(f.read())

process_file('my/test/file.txt')

В документации также предлагается использовать модуль shutil для копирования содержимого файлов:

import os
import shutil

def process_file(filename):
    if not os.path.isfile(filename):
        return
    with open(filename, 'rb') as f_in, gzip.open(filename + '.gz', 'wb') as f_out:
        shutil.copyfileobj(f_in, f_out)

Однако, для более надёжной работы с файлом рекомендуется использовать конструкцию try except, и конечный результат будет выглядеть примерно так:

import os
import shutil

def process_file(filename):
    if not os.path.isfile(filename):
        return
    try: 
        with open(filename, 'rb') as f_in:
            with gzip.open(filename + '.gz', 'wb') as f_out:
                shutil.copyfileobj(f_in, f_out)
    except IOError:
        pass  # обработка случая, когда файл только что был, но пропал
  • Но разве проверка на isfile() это python-way ? Насколько понимаю "нет". Надо обернуть вызов open внутри менеджера контекста и архивацию внутрь try-except блока – sys_dev Aug 22 '15 at 19:41
  • @sys_dev эта информация указана в конце ответа – Timofei Bondarev Aug 22 '15 at 20:35
  • В Вашем последнем варианте после слов "примерно так" следует код в котором все-таки есть 'if not os.path.isfile()'. Эту проверку вообще можно не делать! Оставив только и только try-блок – sys_dev Aug 23 '15 at 05:37
  • @sys_dev Я оставлял эту проверку для того, чтобы различать варианты файл/каталог от ошибок с чтением и отсутствием файла. Мне стоило это упомянуть, да. Вы правильно заметили, она действительно не обязательна. – Timofei Bondarev Aug 23 '15 at 10:36
  • @TimofeyBondarev, для проверки файл/каталог логичнее использовать os.path.isdir(filename) – insolor Aug 23 '15 at 12:14
  • 2 insolor: Посмотрите вариант от @jfs. Он более python-way и решает Вашу задачу! ;) – sys_dev Aug 23 '15 at 14:38
  • 1
    @sys_dev в варианте от jfs, если на вход пришла папка, то исключение не будет брошено, и создастся архив с пустой папкой. – Timofei Bondarev Aug 23 '15 at 20:06
  • @sys_dev, я уже ознакомился, еще в его ответе от 7 апреля (http://ru.stackoverflow.com/q/414593/23044). В одной из моих задач требовалось в том числе и определять, передан ли на вход скрипту путь к директории (через isdir, тогда к нему добавлялось имя файла), и проверять, существует ли файл (проверяется через исключение, но не через isfile). – insolor Aug 23 '15 at 23:27
  • @TimofeyBondarev, тесты показали, что если на вход дан путь к директории, без проверки isfile все-таки выбрасывается IOError (очевидно, директорию нельзя открыть с помощью open(filename, 'rb')). Но вообще, в случае архивации, директория - это по идее особый случай, который возможно потребуется обрабатывать особым образом - например упаковывать содержимое директории. – insolor Aug 24 '15 at 07:43
  • @TimofeyBondarev: архив создаётся в любом случае было исключение или нет. Я потестировал, верно, что если на вход archive.write дать папку, то пустая папка добавляется. Чтобы добавить файлы их необходимо явно указать. Чтобы исключить папки можно явный вызов open(filename, 'rb') добавить. В любом случае isfile() как в моём так и Вашем ответе бесполезен. В Вашем ответе except IOError слишко много ловит. Можно игнорировать только FileNotFoundError во время open(filename, 'rb') - другие ошибки следует пропускать наверх. Если Вы нашли ошибку в моём ответе, то оставьте к нему комментарий – jfs Aug 24 '15 at 14:35
0

Примерно так:

import os
import gzip
...
if not os.path.isdir(dname):
    os.makedirs(dname)
else:
if os.path.exists(fname):
    in=open(fname,'rb')
    out=gzip.open(aname,'wb')
    out.write(in)
    out.close
    in.close
...
Eugene P.
  • 119