Tạo tên tệp tạm thời mà không cần tạo tệp thực bằng Python


98

Câu hỏi, số 10501247 , trong stackoverflow đưa ra câu trả lời về cách tạo tệp tạm thời bằng Python.
Tôi chỉ cần có tên tệp tạm thời trong trường hợp của mình.
Gọi tempfile.NamedTemporaryFile () trả về xử lý tệp sau khi tạo tệp thực.
Có cách nào để chỉ lấy tên tệp không?

# Trying to get temp file path
tf = tempfile.NamedTemporaryFile()
temp_file_name = tf.name
tf.close()
# Here is my real purpose to get the temp_file_name
f = gzip.open(temp_file_name ,'wb')
...

7
NamedTemporaryFileđảm bảo một tên duy nhất, (có thể) bằng cách thử nó và thử lại nếu nó tồn tại. Chỉ lấy một cái tên sẽ không đảm bảo rằng bạn thực sự có thể tạo tệp sau này, bạn đang mở đầu cho điều kiện chủng tộc của người khác sử dụng cùng tên trước bạn.
Joachim Isaksson,

5
@Joachim Đúng, có một điều kiện chủng tộc ở đây và bạn nên tránh điều đó. Tuy nhiên, đôi khi bạn phải chuyển một tên tệp tạm thời cho một hàm (tệp đang mở nội bộ.) Việc có một tên ngẫu nhiên độc đáo mang lại xác suất tốt hơn nhiều rằng điều kiện chủng tộc sẽ không phải là vấn đề. Tôi nghĩ rằng có nhu cầu hợp lệ để cung cấp một tên tệp tạm thời tốt để giảm thiểu khả năng xảy ra lỗi điều kiện cuộc đua. Tất nhiên việc thêm một tiền tố và hậu tố tốt dựa trên quá trình đang chạy và tác vụ đang được thực hiện sẽ giúp giảm nguy cơ xảy ra va chạm.
PolyMesh

@PolyMesh Bạn có thể tránh tình trạng chạy đua bằng cách tạo một thư mục tạm thời sau đó sử dụng một tệp tên cố định bên trong nó. Vì vậy, hàm của bạn chấp nhận một thư mục, thay vì một tệp và luôn tạo cùng một tệp.
DylanYoung

sử dụng tarfile và chuyển nó vào fileobj
Wyrmwood

Câu trả lời:


67

Nếu bạn chỉ muốn có một tên tệp tạm thời, bạn có thể gọi hàm tempfile bên trong _get_candidate_names():

import tempfile

temp_name = next(tempfile._get_candidate_names())
% e.g. px9cp65s

Gọi nextlại, sẽ trả về một tên khác, v.v. Điều này không cung cấp cho bạn đường dẫn đến thư mục tạm thời. Để lấy thư mục 'tmp' mặc định, hãy sử dụng:

defult_tmp_dir = tempfile._get_default_tempdir()
% results in: /tmp 

3
cách tốt hơn để tạo một thư mục tạm thời là cách temp_dir = tempfile.mkdtemp(prefix='some-prefix_')này sẽ tạo một thư mục tạm thời một cách an toàn và trả về một chuỗi với đường dẫn tuyệt đối.
Emanuel Ey

3
Điều quan trọng là chỉ ra rằng next(tempfile._get_candidate_names())không nhất thiết phải trả lại một con đường không tồn tại, đó là lý do tại sao giao diện người dùng cấp tempfile có thể thử nhiều tên cho đến khi một ai không sử dụng được tìm thấy :
Eli Korvigo

1
Người ta có thể sử dụng công khai tempfile.gettempdir()thay vì riêng tư tempfile._get_default_tempdir().
flonk,

@EmanuelEy Điều quan trọng cần nhớ khi sử dụng tempfile.mkdtemp, người dùng có trách nhiệm xóa thư mục tạm thời và nội dung của nó khi thực hiện xong.
Daniel Braun

46

Tôi nghĩ cách dễ nhất, an toàn nhất để làm điều này là:

path = os.path.join(tempfile.mkdtemp(), 'something')

Một thư mục tạm thời được tạo ra mà chỉ bạn mới có thể truy cập, do đó sẽ không có vấn đề gì về bảo mật, nhưng sẽ không có tệp nào được tạo trong đó, vì vậy bạn chỉ cần chọn bất kỳ tên tệp nào bạn muốn tạo trong thư mục đó.

chỉnh sửa: Trong Python 3, bây giờ bạn có thể sử dụng tempfile.TemporaryDirectory()làm trình quản lý ngữ cảnh để xử lý việc xóa cho bạn:

with tempfile.TemporaryDirectory() as tmp:
  path = os.path.join(tmp, 'something')
  # use path

1
Như Daniel Braun đã đề cập ở trên: Điều quan trọng cần nhớ khi sử dụng tempfile.mkdtemp, người dùng có trách nhiệm xóa thư mục tạm thời và nội dung của nó khi thực hiện xong.
bitinerant

4
Nếu bạn sử dụng tempfile.TemporaryDirectory()làm trình quản lý ngữ cảnh, nó sẽ bị xóa cho bạn.
gerrit

17

Nó có thể là một chút muộn, nhưng có điều gì sai với điều này?

import tempfile
with tempfile.NamedTemporaryFile(dir='/tmp', delete=False) as tmpfile:
    temp_file_name = tmpfile.name
f = gzip.open(temp_file_name ,'wb')

37
Mã này thực sự sẽ tạo tệp tạm thời để lấy tên của nó, ngược lại trong câu hỏi nó nói without creating actual file in Python.
Jakub Kukul

Điều này không trả lời câu hỏi
herve

8

tempfile.mktemp() làm cái này.

Nhưng lưu ý rằng nó không được dùng nữa. Tuy nhiên, nó sẽ không tạo tệp và nó là một chức năng công khai trong tempfile so với việc sử dụng _get_candidate_names().

Lý do nó không được dùng nữa là do khoảng cách thời gian giữa việc gọi nó và thực sự cố gắng tạo tệp. Tuy nhiên trong trường hợp của tôi, cơ hội đó là rất nhỏ và ngay cả khi nó thất bại cũng có thể chấp nhận được. Nhưng tùy thuộc vào bạn để đánh giá cho usecase của bạn.


1
“Ngay cả khi nó thất bại vẫn có thể chấp nhận được”; điều kiện cuộc đua không chỉ đơn thuần là rủi ro thất bại, nó còn là rủi ro bảo mật (xem tempfile.mktemptài liệu). Vì vậy, điều đó không nên được coi là chấp nhận được.
bignose

4
@bignose Đây là một vấn đề bảo mật tiềm ẩn . Nó phụ thuộc vào những gì bạn muốn làm, môi trường thực thi mà bạn đang ở, v.v. Điều đó nói rằng: có thể an toàn hơn khi làm điều gì đó như os.path.join(tempfile.mkdtemp(), 'something')Ít nhất thì thư mục đã được tạo (và thuộc sở hữu của bạn, tôi đoán là).
Alec

5

Kết hợp các câu trả lời trước, giải pháp của tôi là:

def get_tempfile_name(some_id):
    return os.path.join(tempfile.gettempdir(), next(tempfile._get_candidate_names()) + "_" + some_id)

Làm some_idtùy chọn nếu không cần thiết cho bạn.


Một lần nữa, tên ứng cử viên có thể không thực sự có sẵn. Đây là câu trả lời chính xác: stackoverflow.com/a/45803022/6387880
j4hangir

1
Tuy nhiên, có khả năng một người cần tạo tên ngẫu nhiên. Tuy nhiên, để chắc chắn, nếu _get_candidate_names()không tồn tại, người ta có thể mặc định cho một số trình tạo chuỗi bán ngẫu nhiên. Ví dụ một số uuid.
juanmirocks

4

Như Joachim Isaksson đã nói trong phần bình luận, nếu bạn chỉ nhận được một cái tên, bạn có thể gặp vấn đề nếu một số chương trình khác sử dụng tên đó trước khi chương trình của bạn sử dụng. Cơ hội là rất mỏng, nhưng không phải là không thể.

Vì vậy, điều an toàn cần làm trong tình huống này là sử dụng hàm tạo GzipFile () đầy đủ, có chữ ký GzipFile( [filename[, mode[, compresslevel[, fileobj]]]]). Vì vậy, bạn có thể chuyển nó vào fileobj đang mở và một tên tệp nữa, nếu bạn muốn. Xem tài liệu gzip để biết chi tiết.

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.