【问题标题】:Best way to generate random file names in Python在 Python 中生成随机文件名的最佳方法
【发布时间】:2023-03-08 13:57:01
【问题描述】:

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

【问题讨论】:

    标签: python random hash


    【解决方案1】:

    您可以使用UUID module 来生成随机字符串:

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

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

    仅在接下来的 100 年每秒生成 10 亿个 UUID 之后,仅创建一个副本的概率约为 50%。如果地球上每个人都拥有 6 亿个 UUID,那么出现重复的概率约为 50%。

    【讨论】:

    • 这在您想要一个唯一的文件名但还不想创建它时也非常有用。
    • 或者使用uuid.uuid4().hex 得到一个没有破折号的十六进制字符串(-)。
    【解决方案2】:

    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'
    

    可以找到使用临时文件的其他示例here

    【讨论】:

    • 下次我重启机器时这些文件会被删除吗?
    • 这个解决方案的问题是它不仅会生成一个文件名,还会生成一个已经打开的文件。如果您需要一个新的、尚不存在的文件的临时文件名(例如,用作 os 命令的输出),则不会这样做。在这种情况下,您可以执行类似 str(uuid.uuid4()) 的操作。
    • @Luca 感谢您的附加评论,这很有用,并注明以供将来参考。但是,OP 明确表示他/她想保存文件,因此需要打开它,所以这个解决方案提供了。
    • 视情况而定。也许他需要该名称来构造适当的服务器调用。不确定。无论如何,您的回复肯定是更常见的情况。
    【解决方案3】:

    一种常见的方法是在文件名中添加时间戳作为前缀/后缀,以与文件建立一些时间关系。如果您需要更多唯一性,您仍然可以在其中添加一个随机字符串。

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

    【讨论】:

    • 在多线程环境中,序列1. Test if file exists, 2. create file. 中可能存在竞争条件如果另一个进程在步骤 1 和 2 之间中断您的进程并创建文件,则当您的代码恢复时它将覆盖另一个进程的文件。
    • @Li-aungYip 另外也可以使用6-8个random character sequence(万一同一秒生成2个文件)。
    • @bobobobo:或者你可以使用tempfile 模块,它会为你处理这个问题。 :)
    • 我建议添加微秒,即...strftime("%y%m%d_%H%M%S%f")
    【解决方案4】:

    如果您不需要文件路径,而只需要具有预定义长度的随机字符串,您可以使用类似的东西。

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

    【讨论】:

      【解决方案5】:

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

      很抱歉冗长的解释,但这确实取决于您的确切用法。

      【讨论】:

        【解决方案6】:

        如果要将原始文件名保留为新文件名的一部分,可以使用当前时间的 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
        

        【讨论】:

        • 为避免:Unicode 对象必须在散列之前进行编码,我改为 md5(str(localtime()).encode('utf-8')).hexdigest()
        • 请注意,任何类型数据的哈希(包括时间戳)本身并不能确保唯一性(与随机选择的字节序列一样)。
        【解决方案7】:

        在这里加上我的两分钱:

        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
        

        【讨论】:

          【解决方案8】:

          由于日期和时间每秒钟都在变化,因此您需要将数据时间与 uuid(通用唯一标识符)连接起来 这是您答案的完整代码

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

          【讨论】:

          • 虽然此代码可以解决问题,including an explanation 说明如何以及为什么解决问题将真正有助于提高您的帖子质量,并可能导致更多的赞成票。请记住,您正在为将来的读者回答问题,而不仅仅是现在提出问题的人。请edit您的回答添加解释并说明适用的限制和假设。
          【解决方案9】:

          我个人更喜欢让我的文本不仅是随机的/唯一的,而且也很漂亮,这就是我喜欢 hashids 库的原因,它可以从整数生成漂亮的随机文本。 可以通过安装

          pip install hashids

          片段:

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

          简短说明:

          Hashids 是一个小型开源库,可从数字生成短的、唯一的、非连续的 id。

          【讨论】:

            【解决方案10】:
            >>> import random
            >>> import string    
            >>> alias = ''.join(random.choice(string.ascii_letters) for _ in range(16))
            >>> alias
            'WrVkPmjeSOgTmCRG'
            

            您可以根据需要将“string.ascii_letters”更改为任何字符串格式以生成任何其他文本,例如手机号码、ID...

            【讨论】:

              【解决方案11】:
              import random
              
              def Generate(): #function generates a random 6 digit number
                  code = ''
                  for i in range(6):
                      code += str(random.randint(0,9))
                  return code
              
              print(Generate()+".txt")
              
              

              【讨论】:

                【解决方案12】:

                在其他一些情况下,如果您需要随机文件名是合理的,请使用faker 模块。这将产生具有通用扩展名的“合理”文件名。此方法可能会在一段时间后发生名称冲突。我认为在前面加上uuid 可能会更好。

                pip install faker
                

                那么,

                from faker import Faker
                
                fake = Faker()
                for _ in range(10):
                    print(fake.file_name())
                
                

                链接到faker 文档:https://faker.readthedocs.io/en/master/index.html

                【讨论】:

                  【解决方案13】:

                  你可以使用随机包:

                  import random
                  file = random.random()
                  

                  【讨论】:

                  • file = str(random.random())
                  • 这是生成随机数,而不是随机文本。
                  • 谢谢。这个答案是一个很好的提交,但它有助于提供更完整的演示。
                  猜你喜欢
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 2011-02-12
                  • 2012-03-17
                  • 2010-11-12
                  • 1970-01-01
                  • 1970-01-01
                  相关资源
                  最近更新 更多