Как мне сохранить на диске временный файл, используя Python? - PullRequest
25 голосов
/ 18 сентября 2008

Я пытаюсь использовать модуль 'tempfile' для манипулирования и создания текстовых файлов. Как только файл будет готов, я хочу сохранить его на диск. Я думал, что это будет так же просто, как использовать 'shutil.copy'. Тем не менее, я получаю сообщение об ошибке «Отказано в доступе»:

>>> import tempfile, shutil
>>> f = tempfile.TemporaryFile(mode ='w+t')
>>> f.write('foo')
>>> shutil.copy(f.name, 'bar.txt')

Traceback (most recent call last):
  File "<pyshell#5>", line 1, in <module>
    shutil.copy(f.name, 'bar.txt')
  File "C:\Python25\lib\shutil.py", line 80, in copy
    copyfile(src, dst)
  File "C:\Python25\lib\shutil.py", line 46, in copyfile
    fsrc = open(src, 'rb')
IOError: [Errno 13] Permission denied: 'c:\\docume~1\\me\\locals~1\\temp\\tmpvqq3go'
>>> 

Разве это не предназначено для использования библиотеки 'tempfile'? Есть лучший способ сделать это? (Может быть, я упускаю из виду что-то очень тривиальное)

Ответы [ 4 ]

37 голосов
/ 06 февраля 2012

хоп правильно, а дф. неверно объясняет причину ошибки.

Поскольку вы еще не позвонили f.close(), файл не удален.

документ для NamedTemporaryFile говорит:

Возможность использования имени для открытия файла во второй раз, когда именованный временный файл все еще открыт, варьируется в зависимости от платформы (его можно использовать в Unix; в Windows NT или более поздней версии это невозможно).

А для TemporaryFile:

В Unix запись каталога для файла удаляется сразу после создания файла. Другие платформы не поддерживают это; Ваш код не должен полагаться на временный файл, созданный с помощью этой функции, имеющий или не имеющий видимое имя в файловой системе.

Поэтому, чтобы сохранить временный файл (в Windows), вы можете сделать следующее:

import tempfile, shutil
f = tempfile.NamedTemporaryFile(mode='w+t', delete=False)
f.write('foo')
file_name = f.name
f.close()
shutil.copy(file_name, 'bar.txt')
os.remove(file_name)

Решение, предоставленное Хансом Сьюннессоном, также отключено, поскольку copyfileobj копирует только из файловоподобного объекта в файлово-подобный объект, а не по имени файла:

shutil.copyfileobj (fsrc, fdst [, length])

Скопируйте содержимое файлового объекта fsrc в файловый объект fdst. Целочисленная длина, если дана, является размером буфера. В частности, отрицательное значение длины означает копирование данных без зацикливания на исходных данных в виде фрагментов; по умолчанию данные читаются порциями, чтобы избежать неконтролируемого потребления памяти. Обратите внимание, что если текущая позиция файла объекта fsrc не равна 0, будет скопировано только содержимое от текущей позиции файла до конца файла.

19 голосов
/ 18 сентября 2008

Файл, который вы создаете с помощью TemporaryFile или NamedTemporaryFile, автоматически удаляется при закрытии, поэтому вы получаете сообщение об ошибке. Если вы не хотите этого, вы можете использовать mkstemp вместо этого (см. Документы для tempfile ).

>>> import tempfile, shutil, os
>>> fd, path = tempfile.mkstemp()
>>> os.write(fd, 'foo')
>>> os.close(fd)
>>> shutil.copy(path, 'bar.txt')
>>> os.remove(path)
12 голосов
/ 21 сентября 2008

Начиная с python 2.6, вы также можете использовать NamedTemporaryFile с опцией delete=, установленной в False. Таким образом, временный файл будет доступен даже после его закрытия.

Обратите внимание, что в Windows (NT и более поздних версиях) вы не можете получить доступ к файлу во второй раз, пока он все еще открыт. Вы должны закрыть его, прежде чем сможете скопировать. Это не так в системах Unix.

5 голосов
/ 18 сентября 2008

Вы всегда можете использовать shutil.copyfileobj , в вашем примере:

new_file = open('bar.txt', 'rw')
shutil.copyfileobj(f, new_file)
...