Python: Làm thế nào để tạo một tên tệp duy nhất?


95

Tôi có một biểu mẫu web python với hai tùy chọn - Tải lên tệpvăn bản . Tôi cần lấy các giá trị từ mỗi giá trị và chuyển chúng sang một chương trình dòng lệnh khác. Tôi có thể dễ dàng chuyển tên tệp với các tùy chọn tải tệp lên, nhưng tôi không chắc cách chuyển giá trị của vùng văn bản.

Tôi nghĩ những gì tôi cần làm là:

  1. Tạo một tên tệp duy nhất
  2. Tạo một tệp tạm thời với tên đó trong thư mục làm việc
  3. Lưu các giá trị được truyền từ textarea vào tệp tạm thời
  4. Thực thi chương trình dòng lệnh từ bên trong mô-đun python của tôi và chuyển cho nó tên của tệp tạm thời

Tôi không chắc chắn về cách tạo một tên tệp duy nhất. Ai có thể cho tôi một số mẹo về cách tạo một tên tệp duy nhất không? Mọi thuật toán, đề xuất và dòng mã đều được đánh giá cao.

Cảm ơn sự quan tâm của bạn


1
Tôi đã chỉnh sửa câu hỏi của bạn để thử và làm cho nó rõ ràng hơn. Hãy cho tôi biết nếu tôi diễn giải điều gì đó không chính xác!
culix

Câu trả lời:


147

Tôi không nghĩ rằng câu hỏi của bạn quá rõ ràng, nhưng nếu tất cả những gì bạn cần là một tên tệp duy nhất ...

import uuid

unique_filename = str(uuid.uuid4())

Xin lỗi, tôi đang làm việc trên nền tảng windows nên không biết cách xử lý quy trình con
MysticCodes

uuid dường như tạo ra một chuỗi dài duy nhất. Tôi không nghĩ sẽ tốt hơn nếu có tên tệp với chuỗi dài và UUID, () trong đó.
MysticCodes

6
Tôi nghĩ uuid.uuid4().hexsẽ là một lựa chọn tốt hơn, xem chi tiết tại đây .
Grey Li

4
@ToloPalmer: Có nhiều khả năng CPU máy tính của bạn bị lỗi xử lý khiến nó tải sai tệp hơn là do UUID được tạo va chạm với bất kỳ giá trị hiện có nào. UUID tạo ra một tên duy nhất trong một mô hình máy tính hiểu rằng không phải tất cả các phép tính đều là toán học thuần túy.
GManNickG

2
Pardon bình luận cũ thiếu hiểu biết của tôi ... Trên thực tế không phải là duy nhất nhưng rất khó có khả năng va chạm, sự lựa chọn rất tốt;)
Tolo Palmer

51

Nếu bạn muốn tạo các tệp tạm thời bằng Python, có một mô-đun được gọi là tempfile trong các thư viện chuẩn của Python. Nếu bạn muốn khởi chạy các chương trình khác để hoạt động trên tệp, hãy sử dụng tempfile.mkstemp () để tạo tệp và os.fdopen () để truy cập các bộ mô tả tệp mà mkstemp () cung cấp cho bạn.

Tình cờ, bạn nói rằng bạn đang chạy các lệnh từ một chương trình Python? Bạn gần như chắc chắn sẽ sử dụng mô-đun quy trình con .

Vì vậy, bạn có thể viết mã trông giống như sau:

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)

Chạy điều đó, bạn sẽ thấy rằng catlệnh hoạt động hoàn toàn tốt, nhưng tệp tạm thời đã bị xóa trong finallykhối. Lưu ý rằng bạn phải xóa tệp tạm thời mà mkstemp () tự trả về - thư viện không có cách nào biết khi nào bạn hoàn thành việc này!

(Chỉnh sửa: Tôi đã cho rằng NamedTemporaryFile đã làm chính xác những gì bạn đang theo đuổi, nhưng điều đó có thể không thuận tiện như vậy - tệp sẽ bị xóa ngay lập tức khi đối tượng tệp tạm thời bị đóng và có các quy trình khác mở tệp trước khi bạn đóng nó sẽ không hoạt động trên một số nền tảng, đặc biệt là Windows. Rất tiếc, tôi thất bại.)


sử dụng NamedTemporaryFile có lẽ là những gì họ muốn (trừ khi họ muốn nó ở lại trên máy chủ, và sau đó họ có thể sử dụng "tempfile.NamedTemporaryFile (delete = False)")
Terence Honles

Tôi có thể đặt tên tệp tạm thời đó là duy nhất không? vì vậy tôi có thể lưu nó sau khi quá trình con hoàn thành với tên duy nhất
MysticCodes

@Terence Honles: Ban đầu, tôi đã đề xuất tempfile.NamedTemporaryFile (), nhưng bạn không thể thực sự sử dụng nó để tạo các tệp tạm thời mà các quy trình khác có thể truy cập trên Windows. Tuy nhiên, NamedTemporaryFile (xóa = Sai) chắc chắn là sạch hơn . @ user343934: tempfile.mkstemp () được đảm bảo cung cấp cho bạn một tên duy nhất mỗi khi nó được gọi - nó tạo tên một cách ngẫu nhiên và nó sử dụng các cơ sở hệ điều hành (O_EXCL, nếu bạn đang thắc mắc) để tránh va chạm.
Richard Barrell

wow, tôi không biết nó không hoạt động trên windows ... fail :( ... Tôi đoán vậy là tốt để biết
Terence Honles

@Terence Honles: NamedTemporaryFile () không thực sự bị lỗi trên Windows (theo như tôi biết), nhưng bạn không thể đóng tệp mà không xóa nó và (theo tôi hiểu ngữ nghĩa tệp trên Windows) không chương trình nào khác có thể mở tệp trong khi bạn mở nó. Tôi có thể sai; ngữ nghĩa của việc có nhiều tiến trình chia sẻ một tệp trong Windows có thể đã thay đổi kể từ lần cuối tôi kiểm tra.
Richard Barrell

32

Các uuidmô-đun sẽ là một lựa chọn tốt, tôi thích sử dụng uuid.uuid4().hexnhư tên tập tin ngẫu nhiên vì nó sẽ trở lại một chuỗi hex không dấu gạch ngang .

import uuid
filename = uuid.uuid4().hex

Kết quả đầu ra sẽ như thế này:

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

1
Có vấn đề gì khi có dấu gạch ngang?
David Lopez

15

Có lẽ bạn cần tệp tạm thời duy nhất?

import tempfile

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

print f.name
f.close()

f là tệp được mở. delete=Falsecó nghĩa là không xóa tệp sau khi đóng.

Nếu bạn cần kiểm soát tên của tệp, có tùy chọn prefix=...suffix=...đối số nhận chuỗi. Xem https://docs.python.org/3/library/tempfile.html .


Điều này rất tốt nếu bạn không cần kiểm soát tên của tệp.
hiwaylon

1
Nó phải là tmpfile.NamedTemporaryFile không chỉ là NamedTemporaryFile.
user1993015

w+blà mặc định mode. Sử dụng bất kỳ tempfilechức năng nào đều có nhược điểm là quyền truy cập tệp không chính xác: tempfiletài liệu để sử dụng os.O_TMPFILElàm mặt nạ, nhưng việc tạo tệp bình thường tôn trọng os.umask().
m8mble

8

Bạn có thể sử dụng mô-đun datetime

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

Lưu ý rằng: Tôi đang sử dụng replacevì dấu hai chấm không được phép trong tên tệp trong nhiều hệ điều hành.

Vậy là xong, điều này sẽ cung cấp cho bạn một tên tệp duy nhất mỗi lần.


2
Trừ khi các tên tệp được tạo ngay sau nhau (ví dụ: trong một vòng lặp). Sau đó, chúng giống nhau.
skjern

1

Tôi đã xem qua câu hỏi này và tôi sẽ thêm giải pháp của mình cho những ai có thể đang tìm kiếm thứ gì đó tương tự. Cách tiếp cận của tôi chỉ là tạo một tên tệp ngẫu nhiên từ các asciiký tự. Nó sẽ là duy nhất với một xác suất tốt.

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
Câu trả lời rõ ràng cho câu hỏi liên quan đến gói uuid. Tuy nhiên, máy chủ mục tiêu của tôi có python 2.4, không có gói uuid và việc nâng cấp không được chủ sở hữu máy chủ cho phép do không tương thích phần mềm cũ, vì vậy câu trả lời này phù hợp với tôi.
Alberto Gaona

1
Tôi đặc biệt thích câu trả lời này: có thể dễ dàng điều chỉnh theo thông số kỹ thuật của dự án.
swdev

1
1) Không có lý do gì để sử dụng đệ quy ở đây, đặc biệt là không bị ràng buộc. 2) Tồn tại điều kiện chạy đua giữa thời gian path.exists()trả về Falsevà thời gian mà người tiêu dùng thực sự mở tệp.
Jonathon Reinhart

1

Điều này có thể được thực hiện bằng cách sử dụng hàm duy nhất trong mô-đun ufp.path .

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

nếu đường dẫn hiện tại tồn tại tệp 'test.ext'. Hàm ufp.path.unique trả về './test (d1) .ext'.


6
ufp là một phần của drupal? không phải là một mô-đun tiêu chuẩn
endolith

1

Để tạo một đường dẫn tệp duy nhất nếu nó tồn tại, hãy sử dụng gói ngẫu nhiên để tạo tên chuỗi mới cho tệp. Bạn có thể tham khảo mã dưới đây cho cùng.

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

Bây giờ bạn có thể sử dụng đường dẫn này để tạo tệp cho phù hợp.


1

Trong trường hợp bạn cần các ID ngắn gọn duy nhất làm tên tệp của mình, hãy thử shortuuid, shortuuid sử dụng các chữ cái và chữ số viết thường và viết hoa, đồng thời xóa các ký tự trông giống nhau như l, 1, I, O và 0.

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

so với

>>> import uuid
>>> unique_filename = str(uuid.uuid4())
>>> len(unique_filename)
36
>>> unique_filename
'2d303ad1-79a1-4c1a-81f3-beea761b5fdf'
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.