Một vấn đề là có một điều kiện chủng tộc trong mã trên của bạn, vì có khoảng cách giữa kiểm tra sự tồn tại và tạo tệp. Có thể có những tác động bảo mật cho điều này (nghĩ về ai đó chèn một liên kết mềm vào một tệp nhạy cảm mà họ không thể ghi đè, nhưng chương trình của bạn chạy với đặc quyền cao hơn có thể) Các cuộc tấn công như thế này là tại sao những thứ như os.tempnam () không được chấp nhận.
Để giải quyết vấn đề này, cách tốt nhất là thực sự thử tạo tệp theo cách bạn sẽ nhận được ngoại lệ nếu không thành công và thành công, trả về đối tượng tệp thực sự mở. Điều này có thể được thực hiện với các hàm os.open mức thấp hơn, bằng cách chuyển cả hai cờ os.O_CREAT và os.O_EXCL. Khi đã mở, hãy trả lại tệp thực tế (và tên tệp tùy chọn) mà bạn tạo. Ví dụ, đây là mã của bạn sửa đổi để sử dụng phương pháp này (trả lại một (tập tin, tên tập tin) tuple):
def unique_file(file_name):
counter = 1
file_name_parts = os.path.splitext(file_name) # returns ('/path/file', '.ext')
while 1:
try:
fd = os.open(file_name, os.O_CREAT | os.O_EXCL | os.O_RDRW)
return os.fdopen(fd), file_name
except OSError:
pass
file_name = file_name_parts[0] + '_' + str(counter) + file_name_parts[1]
counter += 1
[Chỉnh sửa] Trên thực tế, một cách tốt hơn, mà sẽ xử lý các vấn đề trên cho bạn, có lẽ để sử dụng mô-đun tempfile, mặc dù bạn có thể mất quyền kiểm soát việc đặt tên.Dưới đây là một ví dụ của việc sử dụng nó (giữ một giao diện tương tự):
def unique_file(file_name):
dirname, filename = os.path.split(file_name)
prefix, suffix = os.path.splitext(filename)
fd, filename = tempfile.mkstemp(suffix, prefix+"_", dirname)
return os.fdopen(fd), filename
>>> f, filename=unique_file('/home/some_dir/foo.txt')
>>> print filename
/home/some_dir/foo_z8f_2Z.txt
Nhược điểm duy nhất của phương pháp này là bạn sẽ luôn có được một tên tập tin với một số nhân vật ngẫu nhiên trong nó, như không có nỗ lực để tạo ra một tập tin chưa sửa đổi (/home/some_dir/foo.txt) trước tiên. Bạn cũng có thể xem tempfile.TemporaryFile và NamedTemporaryFile, sẽ thực hiện thao tác trên và cũng tự động xóa khỏi đĩa khi đóng.
Có, đây là The_Right_Way để làm điều đó. Tôi ước tôi có thể tự sửa mình và đưa câu trả lời của bạn lên hàng đầu! –
Lỗi đánh máy nhỏ: phải là 'os.O_RDWR' thay vì' os.O_RDRW' – tremby