Python'da gerçek dosya oluşturmadan geçici dosya adları oluşturun


105

Stackoverflow'daki 10501247 numaralı soru Python'da nasıl geçici dosya oluşturulacağına cevap verir.
Benim durumumda sadece geçici dosya adına ihtiyacım var.
Tempfile.NamedTporaryFile () çağrısı, gerçek dosya oluşturulduktan sonra dosya tutamacını döndürür.
Sadece dosya adını almanın bir yolu var mı?

# 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(muhtemelen) deneyerek ve varsa yeniden deneyerek benzersiz bir adı garanti eder. Yalnızca bir ad almak, dosyayı daha sonra gerçekten oluşturabileceğinizi garanti etmez, sizden önce aynı adı kullanan başka birinin yarış durumuna girersiniz.
Joachim Isaksson

5
@ Joachim Doğru, burada bir yarış durumu var ve bundan kaçınmak tercih edilir. Bununla birlikte, bazen bir işleve geçici bir dosya adı aktarmanız gerekir (dosya dahili olarak açılır.) Güzelce rastgele bir ada sahip olmak, yarış koşulunun sorun olmayacağına dair çok daha iyi bir olasılık verir. Bir yarış durumu başarısızlığı olasılığını en aza indirmek için iyi bir geçici dosya adı sağlamaya geçerli bir ihtiyaç olduğunu düşünüyorum. Elbette, yürütülen işleme ve gerçekleştirilen göreve dayalı olarak iyi bir önek ve son ek eklemek, daha da az çarpışma şansı sağlayacaktır.
PolyMesh

@PolyMesh Geçici bir dizin oluşturup sonra içinde sabit bir isim dosyası kullanarak yarış koşulundan kaçınabilirsiniz. Yani işleviniz bir dosya yerine bir dizin kabul eder ve her zaman aynı dosyayı oluşturur.
DylanYoung

tar dosyasını kullanın ve fileobj'yi iletin
Wyrmwood

Yanıtlar:


67

Bir geçici dosya adı istiyorsanız, yalnızca iç geçici dosya işlevini çağırabilirsiniz _get_candidate_names():

import tempfile

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

nextTekrar aramak , başka bir ad döndürür, vb. Bu size geçici klasörün yolunu vermez. Varsayılan 'tmp' dizinini almak için şunu kullanın:

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

3
geçici bir dizin oluşturmanın daha iyi bir yolu temp_dir = tempfile.mkdtemp(prefix='some-prefix_'), güvenli bir şekilde geçici bir dizin oluşturmak ve mutlak yolu içeren bir dize döndürmektir.
Emanuel Ey

3
Bu işaret etmek önemlidir next(tempfile._get_candidate_names())kullanıcı düzeyinde tempfile arayüzler neden en mutlaka, var olmayan bir yol dönmez kullanılmayan biri kadar birkaç isim deneyin bulunursa :
Eli Korvigo

1
tempfile.gettempdir()Özel yerine genel kullanılabilir tempfile._get_default_tempdir().
flonk

@EmanuelEy tempfile.mkdtempKullanıcının geçici dizini ve onunla iş bittiğinde içeriğini silmekten sorumlu olduğunu hatırlamak önemlidir .
Daniel Braun

49

Sanırım bunu yapmanın en kolay ve en güvenli yolu şuna benzer:

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

Yalnızca sizin erişebileceğiniz geçici bir dizin oluşturulur, bu nedenle herhangi bir güvenlik sorunu olmamalıdır, ancak içinde hiçbir dosya oluşturulmayacaktır, böylece o dizinde oluşturmak istediğiniz herhangi bir dosya adını seçebilirsiniz.

düzenleme: Python 3'te artık tempfile.TemporaryDirectory()sizin için silme işleminin üstesinden gelmek için bir bağlam yöneticisi olarak kullanabilirsiniz:

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

1
Daniel Braun'un yukarıda bahsettiği gibi: tempfile.mkdtempKullanıcının, geçici dizini ve onunla iş bittiğinde içeriğini silmekten sorumlu olduğunu hatırlamak önemlidir .
bitinerant

5
tempfile.TemporaryDirectory()Bağlam yöneticisi olarak kullanırsanız , sizin için silinecektir.
gerrit

16

Biraz geç olabilir ama bunda bir sorun mu var?

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

39
Bu kod aslında adını almak için geçici dosyayı oluşturacaktır, oysa soruda yazmaktadır without creating actual file in Python.
Jakub Kukul

Bu soruya cevap vermiyor
Herve

9

tempfile.mktemp() Bunu yap.

Ancak kullanımdan kaldırıldığını unutmayın. Ancak edecek değil dosyası oluşturmak ve bunu kullanmaya kıyasla TempFile bir kamu işlevidir _get_candidate_names().

Kullanımdan kaldırılmasının nedeni, bunu çağırmakla dosyayı gerçekten oluşturmaya çalışmak arasındaki zaman boşluğudur. Ancak benim durumumda bunun şansı çok zayıf ve başarısız olsa bile kabul edilebilir. Ancak kullanım durumunuzu değerlendirmek size kalmış.


1
"Başarısız olsa bile bu kabul edilebilir"; yarış durumu sadece bir başarısızlık riski değildir, bir güvenlik riskidir ( tempfile.mktempbelgelere bakın ). Dolayısıyla bu kabul edilebilir olarak görülmemelidir.
bignose

5
@bignose Olası bir güvenlik sorunu. Bu, ne yapmak istediğinize, içinde bulunduğunuz yürütme ortamına vb. Bağlıdır. Bu, şöyle bir şey yapmak daha güvenli olabilir os.path.join(tempfile.mkdtemp(), 'something')En azından dizin oluşturulur (ve size ait, sanırım).
Alec

5

Önceki cevapları birleştirdiğimde benim çözümüm:

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

some_idSizin için gerekmiyorsa isteğe bağlı yapın .


Yine, aday isimleri gerçekte mevcut olmayabilir. Doğru cevap bu: stackoverflow.com/a/45803022/6387880
j4hangir

1
Ancak, muhtemelen rastgele isimler yaratılması gerekiyor. Yine de, emin olmak için, eğer _get_candidate_names()yoksa, bazı yarı rasgele dizgi üretecine varsayılan olarak atanabilir . Örneğin bazı uuid.
juanmirocks

4

Joachim Isaksson'un yorumlarda söylediği gibi, eğer sadece bir isim alırsanız, programınızdan önce başka bir program bu ismi kullanırsa sorun yaşayabilirsiniz. Şanslar zayıf, ancak imkansız değil.

Dolayısıyla, bu durumda yapılacak güvenli şey, imzaya sahip olan tam GzipFile () yapıcısını kullanmaktır GzipFile( [filename[, mode[, compresslevel[, fileobj]]]]). Böylece, isterseniz ona açık fileobj ve bir dosya adı da iletebilirsiniz. Ayrıntılar için gzip belgelerine bakın.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.