2010-03-30 31 views
10

Tôi có một chương trình Python cần tạo một tệp tạm thời có tên sẽ được mở và đóng vài lần trong suốt chương trình và sẽ bị xóa khi chương trình thoát. Thật không may, không ai trong số các tùy chọn trong tempfile dường như làm việc:Làm cách nào để tạo tệp tạm thời có tên trên các cửa sổ bằng Python?

  • TemporaryFile không có một cái tên có thể nhìn thấy
  • NamedTemporaryFile tạo ra một đối tượng tập tin như thế nào. Tôi chỉ cần một tên tập tin. Tôi đã cố gắng đóng đối tượng nó trả về (sau khi thiết lập delete = False) nhưng tôi nhận được lỗi dòng khi tôi cố gắng để mở tập tin sau này.
  • SpooledTemporaryFile không có tên hiển thị
  • mkstemp trả về cả đối tượng tệp mở và tên; nó không đảm bảo các tập tin bị xóa khi chương trình thoát
  • mktemp trả về tên tập tin, nhưng không đảm bảo các tập tin bị xóa khi chương trình thoát

Tôi đã cố gắng sử dụng mktemp trong vòng người quản lý ngữ cảnh, như vậy:

def get_temp_file(suffix): 
    class TempFile(object): 
     def __init__(self): 
      self.name = tempfile.mktemp(suffix = '.test') 

     def __enter__(self): 
      return self 

     def __exit__(self, ex_type, ex_value, ex_tb): 
      if os.path.exists(self.name): 
       try: 
        os.remove(self.name) 
       except: 
        print sys.exc_info() 

    return TempFile() 

... nhưng điều đó mang lại cho tôi WindowsError(32, 'The process cannot access the file because it is being used by another process'). Tên tệp được sử dụng bởi một tiến trình mà chương trình của tôi sinh ra, và mặc dù tôi đảm bảo rằng quá trình đó kết thúc trước khi tôi thoát ra, dường như có một tình trạng chạy đua ngoài tầm kiểm soát của tôi.

Cách tốt nhất để giải quyết vấn đề này là gì?

Tôi không cần phải lo lắng về vấn đề bảo mật tại đây; đây là một phần của một mô-đun thử nghiệm, do đó, một người nào đó bất chính nhất có thể làm là làm cho các bài kiểm tra đơn vị của chúng tôi thất bại giả. Kinh dị!

+0

Các vấn đề an ninh không ảnh hưởng đến chương trình bằng cách sử dụng tập tin tạm thời, chúng ảnh hưởng đến toàn bộ hệ thống các tập tin tạm thời được tạo ra trên (ví dụ symlinking đến một quan trọng sau khi nó đã được tạo ra). –

+0

Bạn có chắc chắn rằng tất cả các đối tượng tệp đang mở tệp tạm thời được đóng đúng cách không? – user49117

+0

Tên tệp được chuyển đến một tiến trình Windows thông qua Popen(), và khi tôi hoàn thành nó, tôi gọi .flush() trên các dòng .sysin, .sysout và .syserr rồi gọi .wait() trên quá trình. Đó là gói trong một ContextManager, vì vậy tôi chắc chắn nó được gọi. Tôi không chắc mình có thể làm gì khác. –

Trả lời

1

Nếu bạn không quan tâm đến vấn đề bảo mật, điều gì là sai?

tmpfile_name = tempfile.mktemp() 
# do stuff 
os.unlink(tmpfile_name) 

Bạn có thể đang cố gắng thiết kế quá trình này. Nếu bạn muốn đảm bảo rằng tệp này luôn bị xóa khi chương trình thoát, bạn có thể thực thi main() trong một try/finally. Giữ nó đơn giản!

if __name__ == '__main__': 
    try: 
     tmpfile_name = tempfile.mktemp() 
     main() 
    except Whatever: 
     # handle uncaught exception from main() 
    finally: 
     # remove temp file before exiting 
     os.unlink(tmpfile_name) 
+2

os.unlink giống như os.remove, theo tài liệu. Nếu đúng như vậy, tôi sẽ có cùng ngoại lệ, đúng không? –

2

Tôi đã gặp phải sự cố tương tự khi tôi cần lưu tệp được tải lên tệp tạm thời đã mở bằng mô-đun csv. Điều khó chịu nhất là tên tệp trong WindowsError chỉ vào tệp tạm thời, nhưng lưu nội dung tệp tải lên vào bộ đệm StringIO và đẩy dữ liệu đệm vào tệp tạm thời đã khắc phục sự cố. Đối với nhu cầu của tôi là đủ vì các tệp đã tải lên luôn phù hợp với bộ nhớ.

Sự cố chỉ xảy ra khi tôi tải lên tệp có tập lệnh thông qua CGI của Apache, khi tôi chạy tập lệnh tương tự từ bảng điều khiển, tôi không thể tạo lại sự cố.

4

Tôi cần một cái gì đó tương tự như ngày hôm nay và kết thúc bằng văn bản của riêng tôi. Tôi đang sử dụng atexit.register() để đăng ký một hàm gọi lại để xóa tệp khi chương trình thoát.

Lưu ý rằng các tiêu chuẩn mã hóa cho điều này hơi khác so với các tiêu chuẩn mã hóa Python điển hình (camelCase thay vì using_underscores). Điều chỉnh theo ý muốn, tất nhiên.

def temporaryFilename(prefix=None, suffix='tmp', dir=None, text=False, removeOnExit=True): 
    """Returns a temporary filename that, like mkstemp(3), will be secure in 
    its creation. The file will be closed immediately after it's created, so 
    you are expected to open it afterwards to do what you wish. The file 
    will be removed on exit unless you pass removeOnExit=False. (You'd think 
    that amongst the myriad of methods in the tempfile module, there'd be 
    something like this, right? Nope.)""" 

    if prefix is None: 
     prefix = "%s_%d_" % (os.path.basename(sys.argv[0]), os.getpid()) 

    (fileHandle, path) = tempfile.mkstemp(prefix=prefix, suffix=suffix, dir=dir, text=text) 
    os.close(fileHandle) 

    def removeFile(path): 
     os.remove(path) 
     logging.debug('temporaryFilename: rm -f %s' % path) 

    if removeOnExit: 
     atexit.register(removeFile, path) 

    return path 
mã kiểm tra

Super-cơ bản:

path = temporaryFilename(suffix='.log') 
print path 
writeFileObject = open(path, 'w') 
print >> writeFileObject, 'yay!' 
writeFileObject.close() 

readFileObject = open(path, 'r') 
print readFileObject.readlines() 
readFileObject.close() 
Các vấn đề liên quan