Hasilkan nama file sementara tanpa membuat file sebenarnya dengan Python

99

Pertanyaan nomor 10501247 di stackoverflow memberikan jawaban bagaimana cara membuat file sementara dengan Python.
Saya hanya perlu memiliki nama file sementara dalam kasus saya.
Memanggil tempfile.NamedT TemporaryFile () mengembalikan pegangan file setelah pembuatan file sebenarnya.
Apakah ada cara untuk mendapatkan nama file saja?

# 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')
...
Bukit
sumber
7
NamedTemporaryFilemenjamin nama yang unik, (mungkin) dengan mencobanya dan mencoba lagi jika ada. Hanya mendapatkan nama tidak akan menjamin bahwa Anda benar-benar dapat membuat file nanti, Anda membuka kondisi balapan orang lain yang menggunakan nama yang sama sebelum Anda.
Joachim Isaksson
5
@Joachim Benar, ada kondisi balapan di sini dan lebih disukai untuk menghindari itu. Namun, terkadang Anda harus meneruskan nama file sementara ke suatu fungsi (file terbuka terjadi secara internal.) Memiliki nama acak yang bagus memberikan kemungkinan yang jauh lebih baik bahwa kondisi balapan tidak akan menjadi masalah. Saya pikir ada kebutuhan yang valid untuk memberikan nama file sementara yang baik untuk meminimalkan kemungkinan kegagalan kondisi balapan. Tentu saja menambahkan awalan dan sufiks yang baik berdasarkan proses yang sedang berjalan dan tugas yang dilakukan akan memberikan kemungkinan tabrakan yang lebih kecil.
PolyMesh
@PolyMesh Anda dapat menghindari kondisi balapan dengan membuat direktori sementara kemudian menggunakan file nama tetap di dalamnya. Jadi fungsi Anda menerima direktori, bukan file, dan selalu membuat file yang sama.
DylanYoung
menggunakan tarfile dan meneruskannya ke fileobj
Wyrmwood

Jawaban:

67

Jika Anda menginginkan nama file temp saja, Anda dapat memanggil fungsi file temporer _get_candidate_names():

import tempfile

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

Memanggil nextlagi, akan mengembalikan nama lain, dll. Ini tidak memberi Anda jalur ke folder temp. Untuk mendapatkan direktori 'tmp' default, gunakan:

defult_tmp_dir = tempfile._get_default_tempdir()
% results in: /tmp 
Marcin
sumber
3
cara yang lebih baik untuk membuat direktori temp adalah temp_dir = tempfile.mkdtemp(prefix='some-prefix_')yang akan membuat direktori sementara dengan aman dan mengembalikan string dengan jalur absolut.
Emanuel Ey
3
Penting untuk ditunjukkan bahwa next(tempfile._get_candidate_names())tidak selalu mengembalikan jalur yang tidak ada, itulah mengapa antarmuka tempfile tingkat pengguna dapat mencoba beberapa nama sampai yang tidak terpakai ditemukan :
Eli Korvigo
1
Seseorang dapat menggunakan publik tempfile.gettempdir()daripada pribadi tempfile._get_default_tempdir().
flonk
@EmanuelEy Penting untuk diingat ketika menggunakan tempfile.mkdtemppengguna bertanggung jawab untuk menghapus direktori sementara dan isinya ketika selesai dengannya.
Daniel Braun
48

Saya pikir cara termudah dan paling aman untuk melakukan ini adalah seperti:

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

Direktori sementara dibuat yang hanya dapat diakses oleh Anda, jadi seharusnya tidak ada masalah keamanan, tetapi tidak akan ada file yang dibuat di dalamnya, jadi Anda dapat memilih nama file apa pun yang ingin Anda buat di direktori itu.

edit: Dengan Python 3 Anda sekarang dapat menggunakan tempfile.TemporaryDirectory()sebagai pengelola konteks untuk menangani penghapusan untuk Anda:

with tempfile.TemporaryDirectory() as tmp:
  path = os.path.join(tmp, 'something')
  # use path
Alec
sumber
1
Seperti yang Daniel Braun sebutkan di atas: Penting untuk diingat saat menggunakan tempfile.mkdtemppengguna bertanggung jawab untuk menghapus direktori sementara dan isinya ketika selesai dengannya.
bitinerant
4
Jika Anda menggunakan tempfile.TemporaryDirectory()sebagai manajer konteks, itu akan dihapus untuk Anda.
gerrit
17

Mungkin agak terlambat, tetapi apakah ada yang salah dengan ini?

import tempfile
with tempfile.NamedTemporaryFile(dir='/tmp', delete=False) as tmpfile:
    temp_file_name = tmpfile.name
f = gzip.open(temp_file_name ,'wb')
russell
sumber
37
Kode ini sebenarnya akan membuat file sementara untuk mendapatkan namanya, sedangkan dalam pertanyaan tertulis without creating actual file in Python.
Jakub Kukul
Ini tidak menjawab pertanyaan
herve
8

tempfile.mktemp() melakukan hal ini.

Tetapi perhatikan bahwa itu sudah usang. Namun itu tidak akan membuat file dan itu adalah fungsi publik dalam tempfile dibandingkan dengan menggunakan _get_candidate_names().

Alasan tidak digunakan lagi adalah karena jeda waktu antara memanggil ini dan benar-benar mencoba membuat file. Namun dalam kasus saya, peluangnya sangat tipis dan bahkan jika gagal, itu masih dapat diterima. Tetapi terserah Anda untuk mengevaluasi kasus penggunaan Anda.

Zitrax
sumber
1
"Bahkan jika itu akan gagal itu akan diterima"; kondisi balapan bukan hanya risiko kegagalan, itu adalah risiko keamanan (lihat tempfile.mktempdokumentasi). Sehingga seharusnya tidak dianggap bisa diterima.
bignose
4
@bignose Ini adalah masalah keamanan potensial . Itu tergantung pada apa yang ingin Anda lakukan, lingkungan eksekusi tempat Anda berada, dll. Yang mengatakan: mungkin lebih aman untuk melakukan sesuatu seperti. os.path.join(tempfile.mkdtemp(), 'something')Setidaknya ada direktori yang dibuat (dan saya anggap milik Anda).
Alec
5

Menggabungkan jawaban sebelumnya, solusi saya adalah:

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

Jadikan some_idopsional jika tidak diperlukan untuk Anda.

juanmirocks
sumber
Sekali lagi, nama kandidat mungkin tidak benar-benar tersedia. Ini adalah jawaban yang benar: stackoverflow.com/a/45803022/6387880
j4hangir
1
Namun, kemungkinan besar seseorang perlu membuat nama acak. Meskipun demikian, untuk memastikan, jika _get_candidate_names()tidak ada, seseorang dapat secara default menggunakan beberapa generator string semi-acak. Misalnya beberapa uuid.
juanmirocks
4

Seperti yang dikatakan Joachim Isaksson di komentar, jika Anda baru saja mendapatkan nama, Anda mungkin mengalami masalah jika beberapa program lain menggunakan nama itu sebelum program Anda melakukannya. Kemungkinannya tipis, tapi bukan tidak mungkin.

Jadi, hal yang aman untuk dilakukan dalam situasi ini adalah menggunakan konstruktor GzipFile () lengkap, yang memiliki tanda tangan GzipFile( [filename[, mode[, compresslevel[, fileobj]]]]). Jadi Anda bisa meneruskannya ke fileobj yang terbuka, dan juga nama file, jika Anda mau. Lihat dokumen gzip untuk detailnya.

PM 2Ring
sumber