2013-05-29 72 views
5

Tôi có thư viện tương tác với tệp cấu hình. Khi thư viện được nhập, mã khởi tạo đọc tệp cấu hình, có thể cập nhật nó, và sau đó ghi nội dung cập nhật trở lại tệp (ngay cả khi không có gì thay đổi).Khi nào thì Python ghi tệp vào đĩa?

Rất thường xuyên, tôi gặp phải sự cố trong đó nội dung của tệp cấu hình chỉ đơn giản biến mất. Cụ thể, điều này xảy ra khi tôi chạy nhiều lời gọi của một tập lệnh ngắn (sử dụng thư viện), back-to-back, hàng ngàn lần. Nó không bao giờ xảy ra trong cùng một thư mục, dẫn tôi tin rằng đó là một vấn đề hơi ngẫu nhiên - đặc biệt là một điều kiện chủng tộc với IO.

Đây là một nỗi đau để gỡ lỗi, vì tôi không bao giờ có thể tái tạo một cách đáng tin cậy vấn đề và nó chỉ xảy ra trên một số hệ thống. Tôi có một sự nghi ngờ về những gì có thể xảy ra, nhưng tôi muốn xem nếu hình ảnh của tôi về tập tin I/O trong Python là chính xác.

Câu hỏi là, khi nào chương trình Python thực sự ghi nội dung tệp vào đĩa? Tôi nghĩ rằng các nội dung sẽ làm cho nó vào đĩa theo thời gian mà các tập tin đóng cửa, nhưng sau đó tôi không thể giải thích lỗi này. Khi python đóng một tập tin, nó có xóa các nội dung ra đĩa, hay đơn giản là xếp hàng lên hệ thống tập tin? Có thể nội dung tệp có thể được ghi vào đĩa sau khi Python chấm dứt không? Và tôi có thể tránh vấn đề này bằng cách sử dụng fp.flush(); os.fsync(fp.fileno()) (trong đó fp là trình xử lý tệp) không?

Nếu có vấn đề, tôi đang lập trình trên hệ thống Unix (đặc biệt là Mac OS X). Chỉnh sửa: Ngoài ra, hãy nhớ rằng các quy trình không hoạt động đồng thời.

Phụ lục: Đây là tình trạng chủng tộc cụ thể mà tôi nghi ngờ:

  1. Process # 1 được gọi.
  2. Quy trình # 1 mở tệp cấu hình ở chế độ đọc và đóng tệp khi hoàn tất.
  3. Quy trình # 1 mở tệp cấu hình ở chế độ ghi, xóa tất cả nội dung của nó. Việc xóa các nội dung được đồng bộ hóa với đĩa.
  4. Quy trình # 1 ghi nội dung mới vào bộ xử lý tệp và đóng nó.
  5. Quy trình # 1: Khi đóng tệp, Python yêu cầu hệ điều hành gửi hàng đợi ghi các nội dung này vào đĩa.
  6. Process # 1 đóng cửa và thoát
  7. Process # 2 được gọi
  8. Process # 2 mở file cấu hình trong chế độ đọc, nhưng nội dung mới không được đồng bộ hóa được nêu ra. Quy trình # 2 thấy một tệp trống.
  9. Hệ điều hành cuối cùng kết thúc ghi nội dung vào đĩa, sau khi quá trình 2 đọc tệp
  10. Quy trình số 2, cho rằng tệp rỗng, đặt mặc định cho tệp cấu hình.
  11. Quy trình # 2 ghi phiên bản của tệp cấu hình vào đĩa, ghi đè phiên bản cuối cùng.
+5

Không, khi Python đóng tệp, tệp đã được chuyển sang đĩa. Tôi muốn nói quá trình # 2 mở tập tin sớm hơn bạn nghĩ. –

+2

Nếu một số quy trình truy cập một tệp đồng thời và ít nhất một trong số chúng ghi vào nó, bạn phải đồng bộ hóa các quy trình để có được kết quả nhất quán. Đó không phải là bất cứ điều gì cụ thể về Python. –

+2

Ngay cả khi hệ điều hành không ghi dữ liệu vào đĩa, nó sẽ đảm bảo trả lại nội dung của tệp cho quy trình 2. miễn là nó bị xóa khỏi python, vì có bộ nhớ cache được chia sẻ bởi bất kỳ ai truy cập tệp đó . (trừ khi bạn đang chạy các quy trình trên các máy khác nhau trên hệ thống tệp được chia sẻ không được định cấu hình cho tính nhất quán hoặc có điều kiện chủng tộc nơi bạn ghi đè tệp.) – nos

Trả lời

1

Nó gần như chắc chắn không phải lỗi của python. Nếu python đóng tệp, HOẶC thoát sạch (thay vì bị giết bởi tín hiệu), thì hệ điều hành sẽ có nội dung mới cho tệp. Mọi lần mở tiếp theo sẽ trả về nội dung mới. Phải có một cái gì đó phức tạp hơn xảy ra. Dưới đây là một số suy nghĩ.

    Điều bạn mô tả âm thanh có nhiều khả năng là lỗi hệ thống tệp hơn lỗi Python và lỗi hệ thống tệp là khá khó xảy ra.

  1. Lỗi hệ thống tệp có nhiều khả năng xảy ra hơn nếu tệp của bạn thực sự nằm trong hệ thống tệp từ xa. Họ có?

  2. Mọi quy trình có sử dụng cùng một tệp không? Làm "ls -li" trên tệp để xem số inode của nó và xem liệu nó có thay đổi hay không. Trong kịch bản của bạn, nó không nên. Có thể là một cái gì đó đang di chuyển các tập tin, hoặc di chuyển thư mục, hoặc xóa các thư mục và tái tạo chúng? Có liên kết tượng trưng nào không?

  3. Bạn có chắc chắn rằng không có sự trùng lặp trong việc chạy chương trình của bạn? Có bất kỳ quảng cáo nào trong số đó chạy từ một trình bao có "&" ở cuối (ví dụ: ở chế độ nền) không? Điều đó có thể dễ dàng có nghĩa là cái thứ hai được bắt đầu trước khi cái đầu tiên được hoàn thành.

  4. Có chương trình nào khác ghi vào cùng một tệp không?

  5. Đây không phải là câu hỏi của bạn, nhưng nếu bạn cần thay đổi nguyên tử (để bất kỳ chương trình nào chạy song song chỉ thấy phiên bản cũ hoặc phiên bản mới, không bao giờ tệp trống), cách để đạt được ghi nội dung mới vào một tệp khác (ví dụ: "foo.tmp"), sau đó thực hiện os.rename ("foo.tmp", "foo"). Đổi tên là nguyên tử.

+0

Đây là câu trả lời hay nhất tôi có thể hy vọng, tôi cho là vậy. Cảm ơn bạn! – HardlyKnowEm

+0

Khi nó bật ra, một thực tập đã chỉnh sửa một chức năng thư viện để đẻ trứng nhưng một quy trình con Python (sử dụng cùng một mô-đun). Sau khi tôi quay lại sự thay đổi đó, vấn đề dường như biến mất. Điều đó có lẽ cũng giải thích tại sao vấn đề chỉ xảy ra trên máy tính của thực tập sinh. – HardlyKnowEm

+0

Rất vui khi bạn tìm ra! –

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