Python: Benzersiz bir dosya adı nasıl oluşturulur?


95

İki seçenekli bir python web formum var - Dosya yükleme ve metin alanı . Her birinden değerleri alıp başka bir komut satırı programına iletmem gerekiyor. Dosya adını dosya yükleme seçenekleriyle kolayca geçirebilirim, ancak metin alanının değerini nasıl geçireceğimi bilmiyorum.

Sanırım yapmam gereken şey:

  1. Benzersiz bir dosya adı oluşturun
  2. Çalışma dizininde bu isimde geçici bir dosya oluşturun
  3. Metin alanından geçirilen değerleri geçici dosyaya kaydedin
  4. Python modülümün içinden komut satırı programını çalıştırın ve ona geçici dosyanın adını iletin

Benzersiz bir dosya adını nasıl oluşturacağımdan emin değilim. Herhangi biri bana benzersiz bir dosya adı oluşturmayla ilgili bazı ipuçları verebilir mi? Herhangi bir algoritma, öneri ve kod satırı takdir edilmektedir.

İlginiz için teşekkürler


1
Sorunuzu daha net hale getirmek için düzenledim. Bir şeyi yanlış yorumladıysam haberim olsun!
culix

Yanıtlar:


147

Sorunuzun çok açık olduğunu düşünmemiştim, ama tek ihtiyacınız olan benzersiz bir dosya adı ise ...

import uuid

unique_filename = str(uuid.uuid4())

Üzgünüm Windows platformunda çalışıyorum, bu yüzden alt
işlemin

uuid, uzun bir benzersiz dizge oluşturuyor gibi görünüyor. Uzun dize ve UUID () içeren dosya adına sahip olmanın daha iyi olacağını düşünmüyorum.
MysticCodes

6
Bence uuid.uuid4().hexdaha iyi bir seçim olur, ayrıntılara buradan bakın .
Grey Li

4
@ToloPalmer: Bilgisayarınızın CPU'sunun, üretilen bir UUID'nin mevcut herhangi bir değerle çarpışmasından ziyade yanlış dosyayı yüklemesine neden olan bir işleme hatası olması daha olasıdır. UUID, tüm hesaplamanın saf matematik olmadığını anlayan bir hesaplama modelinde benzersiz bir isim üretir.
GManNickG

2
Cehaletimi bağışlayın eski yorumum ... Gerçekten benzersiz değil, ancak çarpışması pek olası değil, bu yüzden iyi bir seçim;)
Tolo Palmer

51

Python'da geçici dosyalar oluşturmak istiyorsanız , Python'un standart kütüphanelerinde tempfile adlı bir modül var. Dosya üzerinde çalışmak üzere başka programlar başlatmak istiyorsanız, dosyaları oluşturmak için tempfile.mkstemp () ve mkstemp () 'nin size verdiği dosya tanımlayıcılarına erişmek için os.fdopen () kullanın.

Bu arada, bir Python programından komut çalıştırdığınızı mı söylüyorsunuz? Alt işlem modülünü neredeyse kesinlikle kullanmalısınız .

Böylece, şuna benzeyen kodu neşeyle yazabilirsiniz:

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)

Bunu çalıştırdığınızda, catkomutun mükemmel bir şekilde çalıştığını görmelisiniz, ancak geçici dosya finallyblokta silindi . Eğer unutmayın sahip kütüphane onunla bitince bilmenin bir yolu var - mkstemp () Kendini döndüren geçici dosyayı silmek!

(Düzenleme: NamedTporaryFile'ın tam olarak peşinde olduğunuz şeyi yaptığını düşünmüştüm, ancak bu o kadar uygun olmayabilir - geçici dosya nesnesi kapatıldığında dosya hemen silinir ve siz kapatmadan önce diğer işlemlerin dosyayı açması bazı platformlarda çalışmaz, özellikle Windows. Üzgünüm, benim açımdan başarısız.)


NamedTporaryFile kullanmak muhtemelen istedikleri şeydir (sunucuda kalmasını istemedikçe ve sonra "tempfile.NamedTporaryFile (delete = False)" seçeneğini kullanabilirler)
Terence Honles

Bu geçici dosya adını da benzersiz yapabilir miyim? böylece alt işlem benzersiz bir adla tamamlandığında daha sonra kaydedebilirim
MysticCodes

@Terence Honles: Başlangıçta tempfile.NamedTporaryFile () öğesini önerdim, ancak bunu diğer işlemlerin Windows'ta erişebileceği geçici dosyalar oluşturmak için gerçekten kullanamazsınız. NamedTporaryFile (delete = False) kesinlikle daha temizdir . @ user343934: tempfile.mkstemp (), her çağrıldığında size benzersiz bir ad vermeyi garanti eder - isimleri rastgele oluşturur ve çarpışmaları önlemek için işletim sistemi olanaklarını (O_EXCL, merak ediyorsanız) kullanır.
Richard Barrell

vay, Windows'ta çalışmadığını bilmiyordum ... başarısız :( ... Sanırım bunu bilmek güzel
Terence Honles

@Terence Honles: NamedTporaryFile () aslında Windows'ta başarısız olmuyor (bildiğim kadarıyla), ancak dosyayı da silmeden kapatamazsınız ve (Windows'ta dosya anlamlarını anladığım kadarıyla) başka hiçbir program dosyayı açarken. Yanlış olabilirim; Windows altında bir dosyayı paylaşan birden fazla işleme sahip olmanın anlamı son kontrol ettiğimden beri değişmiş olabilir.
Richard Barrell 04

32

uuidModül iyi bir seçim olurdu, kullanmayı tercih uuid.uuid4().hexo dönecektir çünkü rastgele dosya adı olarak tire olmadan bir altıgen dizesi .

import uuid
filename = uuid.uuid4().hex

Çıktılar şöyle olmalı:

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

1
Çizgilerin olmasının sorunu nedir?
David Lopez

15

Belki de benzersiz bir geçici dosyaya ihtiyacınız var?

import tempfile

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

print f.name
f.close()

f dosyası açılır. delete=Falsekapattıktan sonra dosyayı silme anlamına gelir.

Dosyanın adı üzerinde kontrole ihtiyacınız varsa, dizeleri alan isteğe bağlı prefix=...ve suffix=...bağımsız değişkenler vardır. Bkz. Https://docs.python.org/3/library/tempfile.html .


Dosyanın adını kontrol etmeniz gerekmiyorsa bu harika.
hiwaylon

1
Yalnızca NamedTporaryFile değil, tmpfile.NamedTporaryFile olmalıdır.
user1993015

w+bvarsayılandır mode. Herhangi bir tempfileişlevselliğin kullanılması, hatalı dosya erişim izinlerinin dezavantajına sahiptir: maske olarak tempfilekullanılacak belgeler os.O_TMPFILE, ancak normal dosya oluşturma hususları os.umask().
m8mble

8

Datetime modülünü kullanabilirsiniz

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

Unutmayın: replaceBirçok işletim sisteminde dosya adlarında iki nokta üst üste kullanılmasına izin verilmediğinden kullanıyorum .

İşte bu, bu size her seferinde benzersiz bir dosya adı verecektir.


2
Dosya adları birbirinin hemen ardından oluşturulmadığı sürece (örneğin bir döngüde). O zaman aynılar.
skjerns

1

Bu soruyla karşılaştım ve benzer bir şey arayanlar için çözümümü ekleyeceğim. Yaklaşımım sadece asciikarakterlerden rastgele bir dosya adı yapmaktı . İyi bir olasılıkla benzersiz olacaktır.

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
Sorunun açık cevabı uuid paketiyle ilgiliydi. Ancak hedef sunucumda python 2.4 var, uuid paketi yok ve eski yazılım uyumsuzlukları nedeniyle yükseltme sunucu sahibi tarafından yetkilendirilmedi, bu nedenle bu yanıt benim için çalışıyor.
Alberto Gaona

1
Bu cevabı özellikle beğendim: proje özelliklerine göre kolayca değiştirilebilir.
swdev

1
1) Burada özyinelemeyi kullanmak için hiçbir neden yok, özellikle de sınırsız. 2) Bu süre arasındaki yarış durumu söz konusudur path.exists()döner Falseve bir tüketici dosya açılmakta o zaman.
Jonathon Reinhart

1

Bu, ufp.path modülündeki benzersiz işlev kullanılarak yapılabilir .

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

mevcut yol 'test.ext' dosyası varsa. ufp.path.unique işlev dönüş './test (d1) .ext'.


6
ufp, drupal'ın bir parçası mı? standart bir modül değil
endolith

1

Varsa benzersiz bir dosya yolu oluşturmak için, dosya için yeni bir dize adı oluşturmak üzere rastgele paket kullanın. Aynı şekilde aşağıdaki koda başvurabilirsiniz.

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

Artık bu yolu, uygun şekilde dosya oluşturmak için kullanabilirsiniz.


1

Dosya adınız olarak kısa benzersiz kimliklere ihtiyacınız olması durumunda, deneyin shortuuid, shortuid küçük harf ve büyük harf ve rakamlar kullanır ve l, 1, I, O ve 0 gibi benzer görünümlü karakterleri kaldırır.

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

nazaran

>>> import uuid
>>> unique_filename = str(uuid.uuid4())
>>> len(unique_filename)
36
>>> unique_filename
'2d303ad1-79a1-4c1a-81f3-beea761b5fdf'
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.