Pythonで実際のファイルを作成せずに一時ファイル名を生成する


98

stackoverflow の質問10501247は、Pythonで一時ファイルを作成する方法を示しています。
私の場合、一時ファイル名だけが必要です。
tempfile.NamedTemporaryFile()を呼び出すと、実際のファイル作成後にファイルハンドルが返されます。
ファイル名のみを取得する方法はありますか?

# Trying to get temp file path
tf = tempfile.NamedTemporaryFile()
temp_file_name = tf.name
tf.close()
# Here is my real purpose to get the temp_file_name
f = gzip.open(temp_file_name ,'wb')
...

7
NamedTemporaryFile(おそらく)試行して、存在する場合は再試行することにより、一意の名前を保証します。名前だけを取得しても、後で実際にファイルを作成できるとは限りません。同じ名前を使用している他のユーザーの競合状態に直面することになります。
Joachim Isaksson 2014年

5
@Joachim確かに、ここには競合状態があり、それを回避することをお勧めします。ただし、一時ファイル名を関数に渡す必要がある場合があります(ファイルのオープンは内部で行われます)。ランダムな名前をうまく使用すると、競合状態が問題にならない可能性が高くなります。競合状態の失敗の可能性を最小限に抑えるために、適切な一時ファイル名を提供することが正当に必要であると思います。もちろん、実行中のプロセスと実行中のタスクに基づいて適切な接頭辞と接尾辞を追加すると、衝突の可能性がさらに低くなります。
PolyMesh 2015

@PolyMesh一時ディレクトリを作成し、その中に固定名ファイルを使用することで、競合状態を回避できます。そのため、関数はファイルではなくディレクトリを受け入れ、常に同じファイルを作成します。
DylanYoung

tarfileを使用してfileobjを渡します
Wyrmwood

回答:


67

一時ファイル名だけが必要な場合は、内部の一時ファイル関数を呼び出すことができます_get_candidate_names()

import tempfile

temp_name = next(tempfile._get_candidate_names())
% e.g. px9cp65s

nextもう一度呼び出すと、別の名前などが返されます。これは一時フォルダへのパスを提供しません。デフォルトの「tmp」ディレクトリを取得するには、次を使用します。

defult_tmp_dir = tempfile._get_default_tempdir()
% results in: /tmp 

3
一時ディレクトリを作成するより良い方法は、一時ディレクトリtemp_dir = tempfile.mkdtemp(prefix='some-prefix_')を安全に作成し、絶対パスを含む文字列を返すことです。
Emanuel Ey

3
それはそれを指摘することは重要だnext(tempfile._get_candidate_names())、必ずしもユーザーレベルの一時ファイルのインタフェースができる理由です非existantパス、返さない未使用のものが見つかるまで、いくつかの名前を試してみてくださいを
イーライKorvigo

1
tempfile.gettempdir()プライベートではなくパブリックを使用できますtempfile._get_default_tempdir()
flonk

@EmanuelEy tempfile.mkdtempユーザーを使用する場合は、一時ディレクトリとその内容を削除する責任があることを覚えておくことが重要です。
Daniel Braun

46

これを行う最も簡単で安全な方法は次のようなものだと思います。

path = os.path.join(tempfile.mkdtemp(), 'something')

自分だけがアクセスできる一時ディレクトリが作成されるので、セキュリティ上の問題はありませんが、そこにファイルは作成されないので、そのディレクトリに作成するファイル名を選択できます。

編集:Python 3 tempfile.TemporaryDirectory()では、削除を処理するコンテキストマネージャーとして使用できます。

with tempfile.TemporaryDirectory() as tmp:
  path = os.path.join(tmp, 'something')
  # use path

1
ダニエルブラウンが前述したように:tempfile.mkdtemp一時ディレクトリとその内容を削除するときは、ユーザーを使用するときに責任があることを覚えておくことが重要です。
飲酒労働者、

4
tempfile.TemporaryDirectory()コンテキストマネージャとして使用すると、削除されます。
ヘリット

17

少し遅いかもしれませんが、何か問題がありますか?

import tempfile
with tempfile.NamedTemporaryFile(dir='/tmp', delete=False) as tmpfile:
    temp_file_name = tmpfile.name
f = gzip.open(temp_file_name ,'wb')

37
このコードは実際にその名前を取得するために一時ファイルを作成しますが、質問ではそれを言いwithout creating actual file in Pythonます。
Jakub Kukul 2016年

これは質問の答えにはなりません
herve '31 / 10/31

8

tempfile.mktemp() これを行う。

ただし、非推奨となっていることに注意してください。ただし、ファイル作成され、を使用する場合と比較してtempfileのパブリック関数_get_candidate_names()です。

これが廃止された理由は、これを呼び出してから実際にファイルを作成しようとするまでの時間のギャップが原因です。しかし私の場合、その可能性は非常に低く、たとえそれが失敗したとしても、それは許容範囲です。しかし、ユースケースを評価するかどうかはあなた次第です。


1
「それが失敗したとしても、それは許容できる」; 競合状態は単なる障害のリスクではなく、セキュリティ上のリスクです(tempfile.mktempドキュメントを参照)。したがって、それは許容できると考えるべきではありません。
bignose 2016

4
@bignoseこれは潜在的なセキュリティ問題です。それはあなたが何をしたいか、あなたがいる実行環境などに依存します。それは言った:そこにあるようなことをする方がより安全かもしれませんos.path.join(tempfile.mkdtemp(), 'something')少なくともディレクトリが作成されます(そしてあなたが所有していると思います)。
アレック

5

以前の答えを組み合わせると、私の解決策は次のとおりです。

def get_tempfile_name(some_id):
    return os.path.join(tempfile.gettempdir(), next(tempfile._get_candidate_names()) + "_" + some_id)

作るsome_idあなたのために必要でない場合は、オプション。


繰り返しになりますが、候補者の名前は実際には入手できない場合があります。:これが正しい答えであるstackoverflow.com/a/45803022/6387880
j4hangir

1
ただし、おそらくランダムな名前を作成する必要があります。それでも、確かに、_get_candidate_names()存在しない場合は、デフォルトのセミランダム文字列ジェネレータを使用できます。たとえば、いくつかのuuid。
juanmirocks

4

Joachim Isakssonがコメントで述べたように、単に名前を取得しただけでは、プログラムが使用する前に他のプログラムがその名前を使用すると問題が発生する可能性があります。可能性はわずかですが、不可能ではありません。

したがって、この状況で安全なことは、シグネチャを持つ完全なGzipFile()コンストラクタを使用することGzipFile( [filename[, mode[, compresslevel[, fileobj]]]])です。したがって、必要に応じて、開いているfileobjとファイル名も渡すことができます。詳細については、gzipドキュメントを参照してください。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.