2011-07-30 29 views
22

Tôi có chương trình python tạo thư mục tmp dưới/temp bằng cách sử dụng tempfile.mkdtemp.
Thật không may, chương trình python đã không xóa thư mục sau khi sử dụng nó. Vì vậy, bây giờ không gian đĩa là thấp.cách xóa thư mục được tạo bởi python tempfile.mkdtemp

Câu hỏi:

  1. Làm thế nào để xóa các thư mục tạm thời rời dưới/temp cách thủ công? Tôi đã cố xóa chúng theo cách thủ công nhưng bị lỗi "cho phép từ chối".
  2. Trong chương trình python, cách xóa thư mục tạm thời sau khi sử dụng chúng.
+2

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? –

+1

Bạn đã thử sử dụng tài khoản/quản trị viên gốc chưa? – Bakuriu

+0

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). –

Trả lời

25

Đọc số documentation, thật đơn giản. ;) Từ tài liệu: thư mục có thể đọc được, có thể ghi và chỉ có thể tìm kiếm được bằng cách tạo ID người dùng.

Để xóa thư mục tạm thử một cái gì đó như thế này:

import errno 
import shutil 
import tempfile 

try: 
    tmp_dir = tempfile.mkdtemp() # create dir 
    # ... do something 
finally: 
    try: 
     shutil.rmtree(tmp_dir) # delete directory 
    except OSError as exc: 
     if exc.errno != errno.ENOENT: # ENOENT - no such file or directory 
      raise # re-raise exception 

Ngoài ra bạn có thể thử tempdir gói hoặc xem nguồn của nó.

+1

điều này dường như không hoạt động. Tôi nhận được lỗi "Bị từ chối" khi chạy nó. Ngoài ra, tôi có nhiều thư mục tmp trên đĩa mà tôi muốn xóa. Tôi cũng không thể xóa chúng theo cách thủ công. Cách thích hợp để xóa cây được tạo bởi mkdtemp là gì? cảm ơn. –

+0

Có lẽ vấn đề trong giá trị của umask trên hệ thống của bạn? Bạn có thể thấy nó trong đầu ra lệnh umask, cố gắng thay đổi nó thành 022 bằng cách thực hiện: umask 022 và sau đó thử lại mã của tôi. – simplylizz

+2

FWIW, câu trả lời của bạn đẹp hơn tài liệu. –

43

Để 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:

+1

Bạn cũng có thể sử dụng [backports.tempfile] (https://stackoverflow.com/questions/19296146/tempfile-temporarydirectory-context-manager-in-python-2-7/39628795#39628795) –

+0

Cảm ơn, giải pháp của bạn rõ ràng và hoạt động tốt. –

Các vấn đề liên quan