Python:如何创建唯一的文件名?


93

我有一个带有两个选项的python网络表单- 文件上传textarea。我需要从每个值中获取值并将它们传递给另一个命令行程序。我可以轻松地通过文件上传选项传递文件名,但是我不确定如何传递textarea的值。

我认为我需要做的是:

  1. 生成唯一的文件名
  2. 在工作目录中使用该名称创建一个临时文件
  3. 将从textarea传递的值保存到临时文件中
  4. 从我的python模块内部执行命令行程序,并将临时文件的名称传递给它

我不确定如何生成唯一的文件名。有人可以给我一些有关如何生成唯一文件名的提示吗?任何算法,建议和代码行都会受到赞赏。

感谢你的关心


1
我编辑了您的问题,以使其更加清楚。让我知道我是否解释错误!
culix 2012年

Answers:


142

我不认为您的问题很清楚,但是如果您需要的是唯一的文件名...

import uuid

unique_filename = str(uuid.uuid4())

抱歉,我在Windows平台上工作,所以不知道如何处理子
进程

uuid似乎会创建一个很长的唯一字符串。我认为最好不要使用带有长字符串和UUID()的文件名。
MysticCodes 2010年

6
我认为uuid.uuid4().hex是更好的选择,请在此处查看详细信息
灰色李

4
@ToloPalmer:您的计算机的CPU更有可能由于处理错误而导致加载错误的文件,而不是生成的UUID与任何现有值发生冲突。UUID在计算模型中产生一个唯一的名称,该名称理解并非所有计算都是纯数学的。
GManNickG

2
请原谅我的无知旧评论……的确不是独一无二的,但不太可能发生冲突,所以是个不错的选择;)
Tolo Palmer

51

如果要用Python制作临时文件,Python的标准库中有一个名为tempfile的模块。如果要启动其他程序对该文件进行操作,请使用tempfile.mkstemp()创建文件,然后使用os.fdopen()访问mkstemp()为您提供的文件描述符。

顺便说一句,您说您是从Python程序运行命令吗?几乎可以肯定,您应该使用子流程模块。

因此,您可以非常愉快地编写如下代码:

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)

运行该cat命令,您应该发现该命令运行良好,但是该临时文件已在该finally块中删除。请注意,您必须删除mkstemp()返回自己的临时文件-库无法知道何时完成操作!

(编辑:我假设NamedTemporaryFile确实完成了您要执行的操作,但这可能不那么方便-在关闭临时文件对象时立即删除该文件,并在关闭该文件之前让其他进程打开该文件不适用于某些平台,尤其是Windows。对不起,我本人失败。)


使用NamedTemporaryFile可能就是他们想要的(除非他们希望它保留在服务器上,然后他们可以使用“ tempfile.NamedTemporaryFile(delete = False)”)
Terence Honles 2010年

我也可以使该临时文件名唯一吗?因此,当子
进程

@Terence Honles:我最初建议使用tempfile.NamedTemporaryFile(),但您不能真正使用它来创建其他进程可以在Windows上访问的临时文件。不过,NamedTemporaryFile(delete = False)当然更干净。@ user343934:保证tempfile.mkstemp()每次调用时都为您提供一个唯一的名称-它会随机生成名称,并使用OS设备(O_EXCL,如果您想知道的话)来避免冲突。
理查德·巴雷尔

哇,我不知道它在Windows上不起作用...失败:( ...我想知道这很高兴
Terence Honles 2010年

@Terence Honles:据我所知,在Windows上NamedTemporaryFile()实际上并没有失败,但是您也不能在不删除文件的情况下关闭文件,而且(据我了解Windows上的文件语义),没有其他程序可以打开打开文件。我可能错了; 自从我上次检查以来,在Windows下让多个进程共享文件的语义可能已更改。
理查德·巴雷尔

31

uuid模块将是一个不错的选择,我更喜欢将其uuid.uuid4().hex用作随机文件名,因为它将返回不带破折号的十六进制字符串

import uuid
filename = uuid.uuid4().hex

输出应如下所示:

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

破折号有什么问题?
大卫·洛佩兹

15

也许您需要唯一的临时文件?

import tempfile

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

print f.name
f.close()

f是打开的文件。delete=False表示关闭后不要删除文件。

如果您需要控制文件名,则有可选prefix=...suffix=...认为需要字符串参数。参见https://docs.python.org/3/library/tempfile.html


如果您不需要控制文件名,那就太好了。
hiwaylon 2014年

1
它应该是tmpfile.NamedTemporaryFile,而不仅仅是NamedTemporaryFile。
user1993015'7

w+b是默认值mode。使用任何tempfile功能的缺点是文件访问权限不正确:将tempfile文档os.O_TMPFILE用作掩码,但要尊重常规文件的创建os.umask()
m8mble

8

您可以使用datetime模块

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

请注意:我正在使用,replace因为在许多操作系统中,文件名中均不允许使用冒号。

就是这样,每次都会为您提供一个唯一的文件名。


2
除非文件名是紧接彼此创建的(例如循环)。然后他们是一样的。
skjerns

1

我遇到了这个问题,我将为那些正在寻找类似内容的人添加我的解决方案。我的方法只是从ascii字符中随机取一个文件名。这将是唯一的可能性很大。

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
这个问题的明显答案与uuid软件包有关。但是我的目标服务器具有python 2.4,由于旧版软件不兼容,没有uuid软件包,服务器所有者也未授权升级,因此此答案对我有用。
阿尔贝托·高纳2014年

1
我特别喜欢这个答案:可以轻松调整项目规格。
swdev 2015年

1
1)这里没有理由使用递归,尤其是无限制的。2)在path.exists()返回False的时间和使用者实际打开文件的时间之间存在竞争条件。
Jonathon Reinhart'4

1

可以使用ufp.path模块中的唯一功能来完成此操作。

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

如果当前路径存在“ test.ext”文件。ufp.path.unique函数返回'./test(d1).ext'。


6
ufp是drupal的一部分吗?不是标准模块
endolith 2015年

1

要创建唯一的文件路径(如果存在),请使用随机包为文件生成新的字符串名称。您可以参考以下代码。

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

现在,您可以使用此路径来相应地创建文件。


0

如果您需要短唯一的ID作为文件名,尝试shortuuidshortuuid使用小写和大写字母和数字,除去外观相似的字符,如1,1,I,O和0。

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

相比

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