Найкращий спосіб генерувати випадкові імена файлів у Python


97

У Python - це хороший чи найкращий спосіб генерувати випадковий текст для додавання до файлу (імені), який я зберігаю на сервері, лише для того, щоб переконатись, що він не перезаписує. Дякую!

Відповіді:


109

Python має можливості для створення тимчасових імен файлів, див. Http://docs.python.org/library/tempfile.html . Наприклад:

In [4]: import tempfile

Кожен виклик tempfile.NamedTemporaryFile()результатів створює інший тимчасовий файл, і його ім'я можна отримати за допомогою .nameатрибута, наприклад:

In [5]: tf = tempfile.NamedTemporaryFile()
In [6]: tf.name
Out[6]: 'c:\\blabla\\locals~1\\temp\\tmptecp3i'

In [7]: tf = tempfile.NamedTemporaryFile()
In [8]: tf.name
Out[8]: 'c:\\blabla\\locals~1\\temp\\tmpr8vvme'

Отримавши унікальне ім’я файлу, його можна використовувати як будь-який звичайний файл. Примітка . За замовчуванням файл буде видалено після його закриття. Однак якщо deleteпараметр False, файл не видаляється автоматично.

Повний набір параметрів:

tempfile.NamedTemporaryFile([mode='w+b'[, bufsize=-1[, suffix=''[, prefix='tmp'[, dir=None[, delete=True]]]]]])

також можна вказати префікс для тимчасового файлу (як один із різних параметрів, які можна вказати під час створення файлу):

In [9]: tf = tempfile.NamedTemporaryFile(prefix="zz")
In [10]: tf.name
Out[10]: 'c:\\blabla\\locals~1\\temp\\zzrc3pzk'

Додаткові приклади роботи з тимчасовими файлами можна знайти тут


1
Чи видаляться ці файли наступного разу, коли я перезавантажу машину?
HelloWorld

15
Проблема цього рішення полягає в тому, що воно генерує не тільки ім'я файлу, але і файл, який уже відкритий. Якщо вам потрібно тимчасове ім'я файлу для нового, ще не існуючого файлу (наприклад, для використання як вихід команди os), це не допоможе. У цьому випадку ви можете зробити щось на зразок str (uuid.uuid4 ()).
Luca

@Luca Дякую за додатковий коментар, який є корисним та зазначений для подальшого використання. Однак OP чітко заявив, що він / вона хоче зберегти файл, отже, його потрібно відкрити, тому це рішення передбачає це.
Левон

Це залежить. Можливо, йому потрібно ім'я для побудови відповідного виклику сервера. Не впевнений. У будь-якому випадку ваша відповідь, звичайно, є найбільш поширеним випадком.
Luca

107

Ви можете використовувати модуль UUID для генерації випадкового рядка:

import uuid
filename = str(uuid.uuid4())

Це правильний вибір, враховуючи, що генератор UUID вкрай малоймовірно створить повторюваний ідентифікатор (у цьому випадку ім'я файлу):

Тільки після генерації 1 мільярда UUID щосекунди протягом наступних 100 років ймовірність створення лише одного дубліката склала б близько 50%. Імовірність одного дубліката склала б близько 50%, якщо кожна людина на землі володіє 600 мільйонами UUID.


17
це також дуже корисно, коли ви хочете отримати унікальне ім'я файлу, але поки не хочете, щоб воно було створене.
Проф. Фалькен

15
Або використовуйте, uuid.uuid4().hexщоб отримати шістнадцятковий рядок без тире ( -).
Rockallite

17

типовим підходом є додавання позначки часу як префікса / суфікса до імені файлу, щоб мати певне часове відношення до файлу. Якщо вам потрібна більша унікальність, ви все одно можете додати до цього випадковий рядок.

import datetime
basename = "mylogfile"
suffix = datetime.datetime.now().strftime("%y%m%d_%H%M%S")
filename = "_".join([basename, suffix]) # e.g. 'mylogfile_120508_171442'

4
У багатопотоковому середовищі можлива умова перегону, яка бере участь у послідовності. 1. Test if file exists, 2. create file.Якщо інший процес перериває ваш між кроками 1 і 2 і створює файл, коли ваш код поновлюється, він замінить файл іншого процесу.
Li-aung Yip

@ Li-aungYip Крім того, також може використовувати 6-8 випадкових послідовностей символів (у випадку, якщо за одну секунду генеруються 2 файли).
bobobobo

@bobobobo: Або ви можете використовувати tempfileмодуль, який обробляє це для вас. :)
Li-aung Yip

Я б запропонував додати мікросекунди, тобто...strftime("%y%m%d_%H%M%S%f")
AstraSerg

8

OP запросив створити випадкові імена файлів, а не випадкові файли . Часи та UUID можуть зіткнутися. Якщо ви працюєте на одній машині (а не спільній файловій системі), і ваш процес / потік не буде набиватися на себе, використовуйте os.getpid (), щоб отримати свій власний PID і використовувати його як елемент унікального імені файлу. Інші процеси, очевидно, не отримали б той самий PID. Якщо ви багатопотокові, отримайте ідентифікатор потоку. Якщо у вас є інші аспекти коду, в яких один потік або процес може генерувати кілька різних темпфілів, можливо, вам доведеться застосувати інший прийом. Індекс, що котиться, може працювати (якщо ви не тримаєте їх так довго або не використовуєте стільки файлів, ви можете турбуватися про перекидання). В такому випадку було б достатньо зберегти загальний хеш / індекс для "активних" файлів.

Так що вибачте за довге пояснення, але воно залежить від вашого точного використання.


8

Якщо вам не потрібен шлях до файлу, а лише випадковий рядок із заданою довжиною, ви можете використати щось подібне.

>>> import random
>>> import string

>>> file_name = ''.join(random.choice(string.ascii_lowercase) for i in range(16))
>>> file_name
'ytrvmyhkaxlfaugx'

7

Якщо ви хочете зберегти оригінальне ім'я файлу як частину нового імені файлу, можна створити унікальні префікси однакової довжини, використовуючи хеші MD5 поточного часу:

from hashlib import md5
from time import localtime

def add_prefix(filename):
    prefix = md5(str(localtime()).encode('utf-8')).hexdigest()
    return f"{prefix}_{filename}"

Виклики до add_prefix ('style.css') генерують послідовність, як:

a38ff35794ae366e442a0606e67035ba_style.css
7a5f8289323b0ebfdbc7c840ad3cb67b_style.css

1
Щоб уникнути: Unicode-об'єкти повинні бути закодовані перед хешуванням я змінив на md5 (str (localtime ()). Encode ('utf-8')). Hexdigest ()
PhoebeB

1
Зауважте, що хеш будь-якого типу даних (включаючи мітку часу) сам по собі не забезпечує унікальність (не більше, ніж випадково обрана послідовність байтів).
Пітер О.

1

Додавши тут свої два центи:

In [19]: tempfile.mkstemp('.png', 'bingo', '/tmp')[1]
Out[19]: '/tmp/bingoy6s3_k.png'

Відповідно до python doc для tempfile.mkstemp, він створює тимчасовий файл найбільш безпечним способом. Зверніть увагу, що файл буде існувати після цього дзвінка:

In [20]: os.path.exists(tempfile.mkstemp('.png', 'bingo', '/tmp')[1])
Out[20]: True

1

Я особисто вважаю за краще, щоб мій текст був не лише випадковим / унікальним, але й красивим, тому мені подобається hashids lib, який генерує приємний на вигляд випадковий текст із цілих чисел. Можна встановити через

pip install hashids

Фрагмент:

import hashids
hashids = hashids.Hashids(salt="this is my salt", )
print hashids.encode(1, 2, 3)
>>> laHquq

Короткий опис:

Hashids - це невелика бібліотека з відкритим кодом, яка генерує короткі унікальні непослідовні ідентифікатори з чисел.


0
>>> import random
>>> import string    
>>> alias = ''.join(random.choice(string.ascii_letters) for _ in range(16))
>>> alias
'WrVkPmjeSOgTmCRG'

Ви можете змінити 'string.ascii_letters' на будь-який формат рядка, як вам подобається, щоб генерувати будь-який інший текст, наприклад мобільний NO, ID ... введіть тут опис зображення


0
import uuid
   imageName = '{}{:-%Y%m%d%H%M%S}.jpeg'.format(str(uuid.uuid4().hex), datetime.now())

1
Хоча цей код може вирішити питання, включаючи пояснення того, як і чому це вирішує проблему, справді допомогло б поліпшити якість вашої публікації, і, можливо, призведе до збільшення кількості голосів. Пам’ятайте, що ви відповідаєте на запитання читачам у майбутньому, а не лише тому, хто задає зараз. Будь ласка, відредагуйте свою відповідь, щоб додати пояснення та вказати, які обмеження та припущення застосовуються.
Богдан Опир

-1

Ви можете використовувати випадковий пакет:

import random
file = random.random()

file = str (random.random ())
anajem

Це генерація випадкових чисел, а не випадковий текст.
user1767754
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.