Лучший способ сгенерировать случайные имена файлов в Python

99

В Python, что является хорошим или лучшим способом сгенерировать случайный текст для добавления к файлу (имени), который я сохраняю на сервере, просто чтобы убедиться, что он не перезаписывается. Спасибо!

Залларак
источник

Ответы:

111

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
Будут ли эти файлы удалены в следующий раз, когда я перезапущу свой компьютер?
SmallChess
16
Проблема с этим решением заключается в том, что оно генерирует не только имя файла, но и уже открытый файл. Если вам нужно временное имя файла для нового, еще не существующего файла (например, для использования в качестве вывода команды os), этого не будет. В этом случае вы можете сделать что-то вроде str (uuid.uuid4 ()).
Luca
@Luca Спасибо за дополнительный комментарий, который полезен и помечен для использования в будущем. Однако OP четко заявил, что он / она хочет сохранить файл, следовательно, необходимо его открыть, поэтому это решение предусматривает это.
Левон
Это зависит. Возможно, ему нужно это имя, чтобы построить соответствующий вызов сервера. Не уверена. Во всяком случае, ваш ответ, безусловно, является более частым случаем.
Luca
113

Вы можете использовать модуль 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-aungYip Кроме того, также можно использовать случайную последовательность из 6-8 символов (в случае, если 2 файла создаются за одну секунду).
bobobobo
@bobobobo: Или вы можете использовать tempfileмодуль, который сделает это за вас. :)
Ли-он Ип
Я бы посоветовал добавить микросекунды, т.е....strftime("%y%m%d_%H%M%S%f")
AstraSerg
8

OP запросил создание случайных имен файлов, а не случайных файлов . Время и UUID могут конфликтовать. Если вы работаете на одной машине (а не в общей файловой системе) и ваш процесс / поток не будет топтаться на себеk, используйте 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'
4xy
источник
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 04
1
Обратите внимание, что хэш любого типа данных (включая временную метку) сам по себе не гарантирует уникальности (как и случайно выбранная последовательность байтов).
Питер О.
1

Добавляем сюда мои два цента:

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

Согласно документу python для tempfile.mkstemp, он создает временный файл наиболее безопасным способом. Обратите внимание, что файл будет существовать после этого вызова:

In [20]: os.path.exists(tempfile.mkstemp('.png', 'bingo', '/tmp')[1])
Out[20]: True
Шахины
источник
1

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

pip install hashids

Фрагмент:

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

Краткое описание:

Hashids - это небольшая библиотека с открытым исходным кодом, которая генерирует короткие уникальные непоследовательные идентификаторы из чисел.

user1767754
источник
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