วิธีที่ดีที่สุดในการสร้างชื่อไฟล์แบบสุ่มใน Python


100

ใน Python อะไรคือสิ่งที่ดีหรือวิธีที่ดีที่สุดในการสร้างข้อความแบบสุ่มเพื่อนำหน้าไฟล์ (ชื่อ) ที่ฉันบันทึกไปยังเซิร์ฟเวอร์เพื่อให้แน่ใจว่าจะไม่เขียนทับ ขอขอบคุณ!

คำตอบ:


112

งูหลามมีสิ่งอำนวยความสะดวกในการสร้างชื่อไฟล์ชั่วคราวดูhttp://docs.python.org/library/tempfile.html ตัวอย่างเช่น:

In [4]: import tempfile

การเรียกแต่ละครั้งให้tempfile.NamedTemporaryFile()ผลลัพธ์ในไฟล์ temp ที่แตกต่างกันและชื่อของมันสามารถเข้าถึงได้ด้วย.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

17
ปัญหาในการแก้ปัญหานี้ไม่เพียง แต่สร้างชื่อไฟล์เท่านั้น แต่ยังสร้างไฟล์ที่เปิดอยู่แล้วด้วย หากคุณต้องการชื่อไฟล์ชั่วคราวสำหรับไฟล์ใหม่ที่ยังไม่มีอยู่ (เช่นเพื่อใช้เป็นเอาต์พุตของคำสั่ง os) สิ่งนี้จะไม่ทำ ในกรณีนี้คุณสามารถทำบางสิ่งเช่น str (uuid.uuid4 ())
Luca

@Luca ขอบคุณสำหรับความคิดเห็นเพิ่มเติมที่เป็นประโยชน์และบันทึกไว้เพื่อใช้อ้างอิงในอนาคต อย่างไรก็ตาม OP ระบุอย่างชัดเจนว่าเขา / เธอต้องการบันทึกไฟล์ดังนั้นจึงต้องเปิดไฟล์ดังนั้นโซลูชันนี้จึงมีให้
Levon

มันขึ้นอยู่กับ. บางทีเขาอาจต้องการชื่อเพื่อสร้างการเรียกเซิร์ฟเวอร์ที่เหมาะสม ไม่แน่ใจ. การตอบกลับของคุณเป็นกรณีที่พบได้บ่อยในอัตราใด ๆ
Luca

115

คุณสามารถใช้โมดูล UUIDเพื่อสร้างสตริงแบบสุ่ม:

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

นี่เป็นตัวเลือกที่ถูกต้องเนื่องจากตัวสร้างUUIDมีโอกาสน้อยมากที่จะสร้างตัวระบุที่ซ้ำกัน (ในกรณีนี้ชื่อไฟล์):

หลังจากสร้าง 1 พันล้าน UUID ทุกวินาทีในอีก 100 ปีข้างหน้าความน่าจะเป็นที่จะสร้างรายการที่ซ้ำกันเพียง 1 รายการจะอยู่ที่ประมาณ 50% ความน่าจะเป็นของการซ้ำกันจะอยู่ที่ประมาณ 50% หากทุกคนบนโลกมี 600 ล้าน UUID


18
นอกจากนี้ยังมีประโยชน์มากเมื่อคุณต้องการชื่อไฟล์ที่ไม่ซ้ำใคร แต่ยังไม่ต้องการสร้าง
ศ. Falken

16
หรือใช้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-objects ต้องเข้ารหัสก่อนที่จะแฮชฉันจึงเปลี่ยนเป็น 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'

ตาม 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' เป็นรูปแบบสตริงใดก็ได้ตามที่คุณต้องการเพื่อสร้างข้อความอื่น ๆ เช่น mobile 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
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.