Để quản lý tài nguyên (như tệp) bằng Python, thực hành tốt nhất là sử dụng từ khóa with
, tự động phát hành tài nguyên (ví dụ: dọn dẹp, như đóng tệp); điều này có sẵn từ Python 2.5.
Từ Python 3.2, bạn có thể sử dụng tempfile.TemporaryDirectory()
thay vì tempfile.mkdtmp()
- đây là có thể sử dụng trong with
và tự động dọn dẹp các thư mục:
from tempfile import TemporaryDirectory
with TemporaryDirectory() as temp_dir:
# ... do something with temp_dir
# automatically cleaned up when context exited
Nếu bạn đang sử dụng một phiên bản cũ của Python (ít nhất là 2,5, do đó có with
), bạn có thể sử dụng backports.tempfile; xem Nicholas Bishop’s answer đến tempfile.TemporaryDirectory context manager in Python 2.7.
Thật dễ dàng và có tính hướng dẫn để cuộn lớp học của riêng bạn, được gọi là context manager. Giá trị trả về của phương thức __enter__()
được ràng buộc với mục tiêu của mệnh đề as
, trong khi phương thức __exit__()
được gọi khi ngữ cảnh được thoát - ngay cả theo ngoại lệ - và thực hiện dọn dẹp.
import shutil
import tempfile
class TemporaryDirectory(object):
"""Context manager for tempfile.mkdtemp() so it's usable with "with" statement."""
def __enter__(self):
self.name = tempfile.mkdtemp()
return self.name
def __exit__(self, exc_type, exc_value, traceback):
shutil.rmtree(self.name)
Bạn có thể đơn giản hóa điều này với trang trí @contextlib.contextmanager
, vì vậy bạn không cần phải viết trình quản lý ngữ cảnh theo cách thủ công. Mã trước khi yield
được thực thi khi nhập ngữ cảnh, giá trị được đặt sẽ được ràng buộc với mục tiêu của as
và mã sau yield
được thực thi khi thoát khỏi ngữ cảnh. Về cơ bản, điều này về cơ bản là coroutine đóng gói việc mua lại và phát hành tài nguyên, với điều khiển năng suất yield
đối với các suite (nội dung) của mệnh đề with
. Lưu ý rằng ở đây bạn do cần phải có một khối try...finally
, vì @contextlib.contextmanager
không bắt ngoại lệ trong yield
- điều này chỉ là yếu tố quản lý tài nguyên thành một coroutine.
from contextlib import contextmanager
import tempfile
import shutil
@contextmanager
def TemporaryDirectory():
name = tempfile.mkdtemp()
try:
yield name
finally:
shutil.rmtree(name)
Như ghi chú simplylizz, nếu bạn không nhớ thư mục đã bị xóa (mà đoạn mã trên giả định không xảy ra), bạn có thể nắm bắt được “Không có tập tin hoặc thư mục” ngoại lệ như sau:
import errno
# ...
try:
shutil.rmtree(self.name)
except OSError as e:
# Reraise unless ENOENT: No such file or directory
# (ok if directory has already been deleted)
if e.errno != errno.ENOENT:
raise
Bạn có thể so sánh với triển khai chuẩn ở tempfile.py
; ngay cả lớp đơn giản này cũng có lỗi và phát triển qua nhiều năm.
Đối với nền tảng về with
, xem:
Tôi không nghĩ rằng câu hỏi của OP đã hiểu. Mã gợi ý là một ví dụ tốt về những gì bạn nên viết trong chương trình của bạn để xóa các thư mục tạm thời được tạo ra. Tuy nhiên, nếu ứng dụng của bạn gặp sự cố (cứng) mà không có cơ hội để chạy mã dọn dẹp đó thì sao? Sau đó, bạn sẽ có một thư mục tạm thời đá xung quanh mà chỉ có thể được xóa bởi quá trình ban đầu đã tạo ra nó (ít nhất là những gì các tài liệu dường như chỉ ra) - làm thế nào là một trong những nghĩa vụ phải làm sạch mà lên? –
Bạn đã thử sử dụng tài khoản/quản trị viên gốc chưa? – Bakuriu
Về 1 (xóa thủ công): đó là vấn đề quyền: sửa các quyền và xóa, ví dụ: 'chmod -R + w/tmp/tmp0ytcxm9c && rm -fr/tmp/tmp0ytcxm9c' (nếu đây là lỗi về quyền, bạn cần là người dùng chạy chương trình hoặc gốc). –