在Python中生成随机文件名的最佳方法


95

在Python中,生成一些随机文本以添加到我要保存到服务器的文件(名称)的一种好的方法或最佳方法是,只是确保它不会被覆盖。谢谢!

Answers:


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

14
该解决方案的问题在于,它不仅会生成文件名,还会生成已经打开的文件。如果您需要一个临时文件名来表示一个新的但尚不存在的文件(例如,用作os命令的输出),则不会这样做。在这种情况下,您可以执行类似str(uuid.uuid4())的操作。

@Luca感谢您的补充评论,该评论很有用,并指出以供将来参考。但是,OP明确表示他/她想保存文件,因此需要打开它,因此此解决方案为此提供了解决方案。
莱文

这取决于。也许他需要这个名字来构造一个适当的服务器调用。不确定。无论如何,您的答复肯定是更常见的情况。

104

您可以使用UUID模块生成随机字符串:

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

鉴于UUID生成器极不可能产生重复的标识符(在这种情况下为文件名),因此这是一个有效的选择:

仅在接下来的100年中每秒生成10亿个UUID之后,仅创建一个副本的可能性就约为50%。如果地球上每个人都拥有6亿个UUID,则重复一次的可能性约为50%。


16
当您想要唯一的文件名但又不想创建它时,这也非常有用。
法尔肯教授

14
或用于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为您处理该模块的模块。:)
Li-aung Yip

我建议增加微秒,即...strftime("%y%m%d_%H%M%S%f")
AstraSerg

8

OP要求创建随机文件名而不是随机文件。时间和UUID可能会发生冲突。如果您在单台机器(不是共享文件系统)上工作,并且进程/线程不会踩踏自身,请使用os.getpid()获取自己的PID,并将其用作唯一文件名的元素。其他进程显然不会获得相同的PID。如果您是多线程的,请获取线程ID。如果在代码的其他方面,单个线程或进程可能会生成多个不同的临时文件,则可能需要使用另一种技术。滚动索引可以正常工作(如果您没有将它们保持太久或使用太多文件,您将担心滚动)。在这种情况下,将全局散列/索引保留为“活动”文件就足够了。

对于冗长的解释,我们深表歉意,但这确实取决于您的确切用法。


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
请注意,任何类型的数据(包括时间戳记)的哈希值本身都不能确保唯一性(除了随机选择的字节序列以外)。
Peter O.

1

在这里加两分钱:

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

根据tempfile.mkstemp的python文档,它将以最安全的方式创建一个临时文件。请注意,该文件将在调用后存在:

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是一个小型的开放源代码库,可从数字生成短的,唯一的,非顺序的ID。


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
尽管这段代码可以解决问题,但包括解释如何以及为何解决该问题的说明,确实可以帮助提高您的帖子质量,并可能导致更多的投票。请记住,您将来会为读者回答问题,而不仅仅是现在问的人。请编辑您的答案以添加说明,并指出适用的限制和假设。
БогданОпир

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.