2011-11-12 31 views
33

Có thể ép buộc tên os.rename ghi đè lên tệp khác nếu tệp đã tồn tại không? Ví dụ trong đoạn mã dưới đây nếu tệp Tests.csv đã tồn tại, nó sẽ được thay thế bằng tệp Tests.txt (cũng được đổi tên thành Tests.csv).Buộc ghi đè trong Os.Rename

os.rename("C:\Users\Test.txt","C:\Users\Tests.csv"); 
+0

Làm cách nào để hủy liên kết tệp mục tiêu đầu tiên, thu hút ngoại lệ tiềm năng? –

+2

Hãy nhớ luôn luôn thoát khỏi dấu gạch chéo ngược trong chuỗi (ví dụ: sử dụng '" C: \\ Users \\ Test.txt "') – 6502

+1

... hoặc sử dụng 'r" C: \ Users \ Test.txt "', nhưng hãy cẩn thận với 'r" C: \\ "'. –

Trả lời

24

Bạn có thể thử shutil.move():

from shutil import move 

move('C:\\Users\\Test.txt', 'C:\\Users\\Tests.csv') 

Hoặc os.remove và sau đó shutil.move:

from os import remove 
from shutil import move 

remove('C:\\Users\\Tests.csv') 
move('C:\\Users\\Test.txt', 'C:\\Users\\Tests.csv') 
+0

@JohnZwinck: không, tính năng này hoạt động trên Windows trong khi 'os.rename' thì không. Xem mã nguồn ['shutil.move'] (http://hg.python.org/cpython/file/9b26fa7f9adf/Lib/shutil.py#l298). –

+1

Vâng, 1 từ tôi cho câu trả lời hiện tại, mặc dù tôi nghi ngờ điều này có thể làm phát sinh một điều kiện chủng tộc. Từ các câu trả lời khác, tôi thu thập điều này trong không thể tránh khỏi trên Windows. –

+0

câu hỏi hỏi "... nếu tồn tại ...", vì vậy loại bỏ nên được gói với nếu hoặc thử logic – denfromufa

0

Từ các tài liệu thư viện chuẩn, “Trên Windows, nếu dst đã tồn tại, OSError sẽ lớn lên ngay cả khi nó là một tập tin; có thể có không có cách nào để thực hiện một đổi tên nguyên tử khi tên dst một tập tin hiện có “

http://docs.python.org/library/os.html#os.rename

Vì vậy, giải pháp duy nhất, không may, sẽ thay đổi hệ điều hành. Windows chỉ đơn giản là không cho phép một rename() trên một tệp hiện có.

7

Trên Unix, nếu dst tồn tại và là tệp, tệp sẽ được thay thế âm thầm nếu người dùng có quyền. Các hoạt động có thể thất bại trên một số hương vị Unix nếu src và dst là trên hệ thống tập tin khác nhau. Nếu thành công, việc đổi tên sẽ là một hoạt động nguyên tử (đây là một yêu cầu POSIX). Trên Windows, nếu dst đã tồn tại, OSError sẽ được nâng lên ngay cả khi nó là một tệp; có thể không có cách nào để thực hiện đổi tên nguyên tử khi dst đặt tên cho một tệp hiện có. http://docs.python.org/library/os.html#os.rename

+6

một lý do khác Windows nên bị trục xuất khỏi trái đất – MFB

+0

Hoặc không phải vì điều này là hoàn toàn sai, API MoveFile là nguyên tử – paulm

2

đủ Funny, tài liệu cho os.rename() nói nó thay thế các mục tiêu trên các hệ thống Unix, nhưng trên Windows nó không. Họ đề cập đến một cái gì đó mơ hồ về nó là không thể thực hiện đổi tên nguyên tử nếu đích đến tồn tại trên Windows, mà IMO là hầu như không đủ lý do để không hỗ trợ nó.

Bạn nên bắt OSError (đích tồn tại trên Windows) và xóa đích và thử lại, tôi giả sử.

8

Vì số documentation cho biết không thể đảm bảo hoạt động đổi tên nguyên tử trên Windows nếu tệp tồn tại nên những gì Python làm là yêu cầu tự làm bước đôi os.remove + os.rename, xử lý lỗi tiềm ẩn.

Trên hệ thống Unix rename ghi đè đích đến nếu tồn tại (vì thao tác được đảm bảo là nguyên tử).

Lưu ý rằng trên cửa sổ cũng có thể xóa tệp đích sẽ không thành công ngay cả khi bạn có quyền vì tệp có thể đang được sử dụng. Đây là một hạn chế thiết yếu khác của hệ thống tệp windows và bạn phải tự xử lý nó trong mã.

19

Kể từ Python 3.3, bây giờ có một giải pháp đa nền tảng tiêu chuẩn, os.replace:

Đổi tên tập tin hoặc thư mục src dst để. Nếu dst là một thư mục, OSError sẽ là được nêu ra. Nếu dst tồn tại và là một tập tin, nó sẽ được thay thế âm thầm nếu người dùng có quyền.Thao tác có thể thất bại nếu src và dst nằm trên các hệ thống tệp khác nhau. Nếu thành công, việc đổi tên sẽ là hoạt động nguyên tử (đây là yêu cầu POSIX).

Tính khả dụng: Unix, Windows.

Tính năng mới trong phiên bản 3.3.

Tuy nhiên, trái với tài liệu, trên Windows, nó không được đảm bảo là nguyên tử (trong Python 3.4.4). Đó là bởi vì internally nó sử dụng MoveFileEx trên Windows, không đảm bảo như vậy.

+0

MoveFileEx không nguyên tử như thế nào? – paulm

+0

@paulm Nếu bạn kiểm tra trang MSDN của nó, nó sẽ không bao giờ hứa hẹn về nguyên tử và thậm chí còn gợi ý 'MoveFileTransacted' thay thế. Trong thực tế, 'MoveFileEx' là nguyên tử trên các hệ thống tệp cục bộ nhưng không nguyên tử trên các hệ thống tệp mạng (tốt, thực sự nó phụ thuộc vào máy chủ). Nhưng ngay cả đối với FSes địa phương, nguyên tử của nó không phải là hợp đồng. – atzz