Python:一意のファイル名を作成するには?


93

私は、ファイルのアップロードテキストエリアの 2つのオプションを持つpython webフォームを持っています。それぞれから値を取得して、別のコマンドラインプログラムに渡す必要があります。ファイルアップロードオプションでファイル名を簡単に渡すことができますが、textareaの値を渡す方法がわかりません。

私がする必要があるのは、

  1. 一意のファイル名を生成する
  2. 作業ディレクトリにその名前の一時ファイルを作成します
  3. textareaから渡された値を一時ファイルに保存します
  4. 私のpythonモジュール内からコマンドラインプログラムを実行し、一時ファイルの名前を渡します

一意のファイル名を生成する方法がわかりません。一意のファイル名を生成する方法に関するヒントを誰かに教えてもらえますか?アルゴリズム、提案、コード行は大歓迎です。

ご心配をありがとう


1
あなたの質問を編集して、より明確にするようにしました。間違って解釈した場合はお知らせください!
culix 2012

回答:


142

あなたの質問はそれほど明確ではないと思いましたが、必要なのは一意のファイル名だけです...

import uuid

unique_filename = str(uuid.uuid4())

申し訳ありませんが、Windowsプラットフォームで作業しているため、サブプロセスの処理方法がわかりません
MysticCodes

uuidは長い一意の文字列を作成するようです。長い文字列とUUID()を含むファイル名を含めるのは良いとは思いません。
MysticCodes

6
uuid.uuid4().hexはより良い選択だと思います、詳細はこちらをご覧ください。
Grey Li

4
@ToloPalmer:生成されたUUIDが既存の値と衝突するよりも、コンピューターのCPUに間違ったファイルをロードさせる処理エラーがある可能性が高いです。UUIDは、すべての計算が純粋な数学であるとは限らないことを理解する計算のモデルで一意の名前を生成します。
GManNickG 2017

2
私の無知の古いコメントを許してください...確かにユニークではありませんが、衝突する可能性は非常に低いので、良い選択です;)
Tolo Palmer

51

Pythonで一時ファイルを作成する場合は、Pythonの標準ライブラリにtempfileと呼ばれるモジュールがあります。他のプログラムを起動してファイルを操作する場合は、tempfile.mkstemp()を使用してファイルを作成し、os.fdopen()を使用してmkstemp()が提供するファイル記述子にアクセスします。

ちなみに、あなたはあなたがPythonプログラムからコマンドを実行していると言いますか?ほとんどの場合、サブプロセスモジュールを使用する必要があります。

したがって、次のようなコードを非常に陽気に書くことができます。

import subprocess
import tempfile
import os

(fd, filename) = tempfile.mkstemp()
try:
    tfile = os.fdopen(fd, "w")
    tfile.write("Hello, world!\n")
    tfile.close()
    subprocess.Popen(["/bin/cat", filename]).wait()        
finally:
    os.remove(filename)

これを実行すると、catコマンドは完全に機能することがわかりますが、一時ファイルはfinallyブロックから削除されています。mkstemp()が自分に返す一時ファイルを削除する必要あることに注意してください。ライブラリには、いつ使用したかを知る方法がありません。

(編集:私はNamedTemporaryFileがあなたがしたいことを正確に行ったと思っていましたが、それはそれほど便利ではないかもしれません-一時ファイルオブジェクトが閉じられるとすぐにファイルが削除され、閉じる前に他のプロセスにファイルを開かせます一部のプラットフォーム、特にWindowsでは機能しません。申し訳ありませんが、私の側では失敗します。)


NamedTemporaryFileを使用することは、おそらく彼らが望んでいることです(サーバーに残したい場合は、 "tempfile.NamedTemporaryFile(delete = False)"を使用できます)
Terence Honles

その一時ファイル名も一意にできますか?後でサブプロセスが一意の名前で完了したときに保存できます
MysticCodes

@Terence Honles:tempfile.NamedTemporaryFile()を最初に提案しましたが、実際にそれを使用して、他のプロセスがWindowsでアクセスできる一時ファイルを作成することはできません。ただし、NamedTemporaryFile(delete = False)の方がきれいです。@ user343934:tempfile.mkstemp()は、呼び出されるたびに一意の名前を付けることが保証されています-名前がランダムに生成され、OS機能(不思議な場合はO_EXCL)を使用して衝突を回避します。
Richard Barrell

うわー、それがWindowsで機能しないことを知りませんでした...失敗:( ...それは知っていると良いと思います
Terence Honles

@Terence Honles:NamedTemporaryFile()は実際には(私が知る限り)Windowsでは失敗しませんが、ファイルも削除せずに閉じることはできません。(Windowsでのファイルセマンティクスを理解しているように)他のプログラムはファイルを開くことができません。ファイルを開いている間。私は間違っているかもしれません; Windowsで複数のプロセスがファイルを共有するためのセマンティクスは、最後に確認してから変更されている可能性があります。
Richard Barrell

31

uuidモジュールは、私が使用することを好む、選ぶとよいでしょうuuid.uuid4().hex、それが返されますので、ランダムなファイル名としてダッシュせずに16進文字列を

import uuid
filename = uuid.uuid4().hex

出力は次のようになります。

>>> import uuid
>>> uuid.uuid()
UUID('20818854-3564-415c-9edc-9262fbb54c82')
>>> str(uuid.uuid4())
'f705a69a-8e98-442b-bd2e-9de010132dc4'
>>> uuid.uuid4().hex
'5ad02dfb08a04d889e3aa9545985e304'  # <-- this one

ダッシュがあることの問題は何ですか?
David Lopez

15

多分あなたはユニークな一時ファイルが必要ですか?

import tempfile

f = tempfile.NamedTemporaryFile(mode='w+b', delete=False)

print f.name
f.close()

fは開かれたファイルです。delete=False閉じた後にファイルを削除しないことを意味します。

ファイル名を制御する必要がある場合はprefix=...suffix=...文字列を取るオプションの引数があります。https://docs.python.org/3/library/tempfile.htmlを参照してください


これは、ファイルの名前を制御する必要がない場合に最適です。
hiwaylon 2014年

1
NamedTemporaryFileだけでなく、tmpfile.NamedTemporaryFileにする必要があります。
user1993015 2017

w+bがデフォルトですmode。任意のtempfile機能を使用すると、ファイルアクセス権限が正しくないという欠点があります。マスクとしてtempfile使用するドキュメントos.O_TMPFILEですが、通常のファイル作成は尊重されos.umask()ます。
m8mble 2018

8

日時モジュールを使用できます

import datetime
uniq_filename = str(datetime.datetime.now().date()) + '_' + str(datetime.datetime.now().time()).replace(':', '.')

注:replace多くのオペレーティングシステムではファイル名にコロンを使用できないため、私は使用しています。

それだけです。これにより、毎回一意のファイル名が得られます。


2
ファイル名が次々に作成されない限り(ループ内など)。それから彼らは同じです。
skjerns、

1

私はこの質問に出くわしました、そして私は同様の何かを探しているかもしれない人々のために私の解決策を追加します。私のアプローチは、ascii文字からランダムなファイル名を作成することでした。可能性が高いユニークなものになります。

from random import sample
from string import digits, ascii_uppercase, ascii_lowercase
from tempfile import gettempdir
from os import path

def rand_fname(suffix, length=8):
    chars = ascii_lowercase + ascii_uppercase + digits

    fname = path.join(gettempdir(), 'tmp-'
                + ''.join(sample(chars, length)) + suffix)

    return fname if not path.exists(fname) \
                else rand_fname(suffix, length)

1
質問に対する明白な答えは、uuidパッケージに関するものでした。ただし、私のターゲットサーバーにはpython 2.4があり、uuidパッケージがなく、アップグレードはレガシーソフトウェアの非互換性のためにサーバーの所有者によって承認されなかったため、この答えは私にとってはうまくいきます。
Alberto Gaona 2014年

1
私はこの答えが特に好きです。プロジェクトの仕様に合わせて簡単に調整できます。
swdev 2015

1
1)ここでは、特に制限なしで、再帰を使用する理由はありません。2)path.exists()戻っFalseた時刻と、コンシューマーが実際にファイルを開いた時刻の間に競合状態が存在します。
Jonathon Reinhart 2017

1

これは、ufp.pathモジュールの一意の関数を使用して行うことができます。

import ufp.path
ufp.path.unique('./test.ext')

現在のパスが 'test.ext'ファイルに存在する場合。ufp.path.unique関数は './test(d1).ext'を返します。


6
ufpはdrupalの一部ですか?標準モジュールではない
エンドリス

1

存在する場合に一意のファイルパスを作成するには、ランダムパッケージを使用してファイルの新しい文字列名を生成します。以下のコードを参照してください。

import os
import random
import string

def getUniquePath(folder, filename):    
    path = os.path.join(folder, filename)
    while os.path.exists(path):
         path = path.split('.')[0] + ''.join(random.choice(string.ascii_lowercase) for i in range(10)) + '.' + path.split('.')[1]
    return path

これで、このパスを使用して、それに応じてファイルを作成できます。


0

ファイル名として短い一意のIDが必要な場合は、try shortuuidshortuuidは小文字と大文字と数字を使用し、l、1、I、O、0などの類似した文字を削除します。

>>> import shortuuid
>>> shortuuid.uuid()
'Tw8VgM47kSS5iX2m8NExNa'
>>> len(ui)
22

に比べ

>>> import uuid
>>> unique_filename = str(uuid.uuid4())
>>> len(unique_filename)
36
>>> unique_filename
'2d303ad1-79a1-4c1a-81f3-beea761b5fdf'
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.