web-dev-qa-db-ja.com

Pythonを使用して一時ファイルをディスクに永続化するにはどうすればよいですか?

テキストファイルの操作と作成に「tempfile」モジュールを使用しようとしています。ファイルの準備ができたら、ディスクに保存したいと思います。 'shutil.copy'を使用するのと同じくらい簡単だと思いました。ただし、「許可が拒否されました」IOErrorが発生します。

>>> 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'ライブラリを使用する場合、これは意図されていませんか?これを行うためのより良い方法はありますか? (たぶん私は非常に些細なことを見落としています)

25
Ray Vega

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)
20
dF.

ホップは正しい、そしてdF。エラーが発生する理由が正しくありません。

まだf.close()を呼び出していないため、ファイルはnot削除されます。

doc for 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はファイル名ではなく、ファイルのようなオブジェクトからファイルのようなオブジェクトにのみコピーするため、HansSjunnessonが提供したソリューションもオフになっています。

shutdown.copyfileobj(fsrc、fdst [、length])

ファイルのようなオブジェクトfsrcの内容をファイルのようなオブジェクトfdstにコピーします。整数の長さは、指定されている場合、バッファーサイズです。特に、負の長さの値は、ソースデータをチャンクでループせずにデータをコピーすることを意味します。デフォルトでは、制御されていないメモリ消費を避けるために、データはチャンクで読み取られます。 fsrcオブジェクトの現在のファイル位置が0でない場合、現在のファイル位置からファイルの終わりまでの内容のみがコピーされることに注意してください。

37
K Z

python 2.6から、delete=オプションをFalseに設定してNamedTemporaryFileを使用することもできます。これにより、一時ファイルを閉じた後でもアクセスできるようになります。

Windows(NT以降)では、ファイルが開いている間はファイルに再度アクセスできないことに注意してください。コピーする前に閉じる必要があります。これはUnixシステムには当てはまりません。

12
user3850

あなたの例では、いつでもshutil.copyfileobjを使用できます。

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