Как убедиться, что файл закрыт для записи на Python?

Проблема, описанная здесь, сначала рассматривалась как будто это можно было решить, просто закрыв электронную таблицу в Excel перед запуском программы.

Однако оказывается, что закрытие Excel является необходимым, но недостаточным условием. Проблема все еще возникает, но не на каждой машине Windows и не каждый раз (иногда это происходит после одного выполнения, иногда после двух).

Я изменил программу так, что теперь она читает из одной электронной таблицы и записывает в другую, но проблема остается. Я даже продолжаю программно уничтожать все устаревшие процессы Python перед запуском программы. По-прежнему никакой радости.

Функция openpyxl save() создает экземпляр ZipFile таким образом:

archive = ZipFile(filename, 'w', ZIP_DEFLATED, allowZip64=True)

... с Zipfile, затем используя это, чтобы попытаться открыть файл в режиме 'wb', таким образом:

if isinstance(file, basestring):
    self._filePassed = 0
    self.filename = file
    modeDict = {'r' : 'rb', 'w': 'wb', 'a' : 'r+b'}
    try:
        self.fp = open(file, modeDict[mode])
    except IOError:
        if mode == 'a':
            mode = key = 'w'
            self.fp = open(file, modeDict[mode])
        else:
            raise

Согласно документам:

В Windows добавление «b» к режиму открывает файл в двоичном режиме, поэтому существуют также такие режимы, как «rb», «wb» и «r + b». Python в Windows делает различие между текстовыми и двоичными файлами; символы конца строки в текстовых файлах автоматически слегка изменяются при чтении или записи данных. Эта негласная модификация файловых данных подходит для текстовых файлов ASCII, но приведет к повреждению двоичных данных, как в файлах JPEG или EXE. Будьте очень осторожны при чтении и записи таких файлов в двоичном режиме. В Unix не помешает добавить к режиму букву «b», так что вы можете использовать его независимо от платформы для всех двоичных файлов.

... что объясняет, почему необходимо использовать режим 'wb'.

Есть ли что-то в открытии файла Python, которое могло бы оставить файл в некотором состоянии «открытости»?

Windows: 8

Python: 2.7.10

openpyxl: последняя версия


person Pyderman    schedule 22.07.2015    source источник
comment
Не уверен, что понимаю вашу проблему, но не следует ли вам просто self.fp.close() в конце операции?   -  person Radosław Roszkowiak    schedule 22.07.2015
comment
Было бы полезно записывать версии Windows, python и openpyxl, когда они работают, а когда нет. Вы не задумывались о заполнении баг-репорта?   -  person Eric Levieil    schedule 22.07.2015
comment
@rroszkowiak Приведенный выше код является выдержкой из ZipFile, части стандартной библиотеки Python. Я бы предпочел не трогать его.   -  person Pyderman    schedule 22.07.2015
comment
В Python файлы нужно явно закрывать. Не полагайтесь на сборку мусора, чтобы закрыть файл за вас, потому что сборка мусора происходит в непредсказуемое время - или не происходит вообще, пока программа не завершится.   -  person Craig S. Anderson    schedule 22.07.2015
comment
@ CraigS.Anderson Лучше использовать синтаксис with.   -  person Alyssa Haroldsen    schedule 22.07.2015
comment
Извините, я не понимаю, в чем проблема. Закрытие Python происходит немедленно. Если вызывается Excel, это, скорее всего, является причиной каких-либо проблем с совместным доступом к файлам. Он небрежно закрывает файл данных после его чтения и намеренно создает файл блокировки файла, который сохраняется в течение многих секунд после того, как он больше не нужен. Можете ли вы сузить круг симптомов, которые вы видите?   -  person wallyk    schedule 22.07.2015
comment
@ CraigS.Anderson Да, последняя строка в функции openpyxl save действительно закрывает файл.   -  person Pyderman    schedule 22.07.2015
comment
Что это за третий или четвертый вопрос по той же проблеме? Мы не можем видеть ваш код и не можем проверить вашу машину, и без этого я не думаю, что проблема может быть должным образом исследована.   -  person Charlie Clark    schedule 23.07.2015
comment
@CharlieClark В отсутствие какого-либо кода вы сами все же смогли дать совет в моем предыдущем вопросе, который помог мне справиться с первым проявлением этой проблемы. И теперь предложения другого респондента (и ответ ниже) приближают меня к окончательному решению этой проблемы. Вот почему мне нравится Stack Overflow. Даже в отсутствие кода вы, ребята, достаточно умны, чтобы мыслить нестандартно и творчески предлагать решения.   -  person Pyderman    schedule 23.07.2015


Ответы (1)


Два предложения:

Во-первых, используйте with, чтобы правильно закрыть файл.

with open("some.xls", "wb") as excel_file:
    #Do something

В конце файл закроется сам по себе (см. this ).

Вы также можете сделать копию файла и работать с скопированным файлом.

import shutil
shutil.copyfile(src, dst)

https://docs.python.org/2/library/shutil.html#shutil.copyfile

person AdriVelaz    schedule 23.07.2015
comment
Это код openpyxl, который открывает файл, поэтому я бы предпочел оставить это в покое. Тем не менее, ваше предложение скопировать файл является отличным, и я обязательно опробую его. - person Pyderman; 23.07.2015