Tôi có một mô-đun urllib2 bộ nhớ đệm, mà thỉnh thoảng bị treo vì đoạn mã sau:Race điều kiện tạo thư mục trong Python
if not os.path.exists(self.cache_location):
os.mkdir(self.cache_location)
Vấn đề là, vào thời điểm dòng thứ hai đang được thực hiện, các thư mục có thể tồn tại và sẽ báo lỗi:
File ".../cache.py", line 103, in __init__ os.mkdir(self.cache_location) OSError: [Errno 17] File exists: '/tmp/examplecachedir/'
Điều này là do tập lệnh được khởi chạy đồng thời nhiều lần, bởi mã của bên thứ ba mà tôi không kiểm soát được.
Mã này (trước khi tôi đã cố gắng để sửa chữa các lỗi) có thể được tìm thấy here, on github
tôi không thể sử dụng tempfile.mkstemp, vì nó giải quyết được tình trạng chủng tộc bằng cách sử dụng một thư mục có tên ngẫu nhiên (tempfile.py source here), mà sẽ đánh bại mục đích của bộ nhớ cache.
Tôi không muốn chỉ đơn giản là loại bỏ các lỗi, như lỗi tương tự Errno 17 lỗi được nâng lên nếu tên thư mục tồn tại như một tập tin (một lỗi khác nhau), ví dụ:
$ touch blah $ python >>> import os >>> os.mkdir("blah") Traceback (most recent call last): File "", line 1, in OSError: [Errno 17] File exists: 'blah' >>>
tôi không thể sử dụng threading.RLock
vì mã được gọi từ nhiều quy trình.
Vì vậy, tôi cố gắng viết một khóa tập tin dựa trên đơn giản (that version can be found here), nhưng điều này có một vấn đề: nó tạo ra lockfile lên mức trên, vì vậy /tmp/example.lock
cho /tmp/example/
, mà phá vỡ nếu bạn sử dụng /tmp/
như một dir cache (như nó cố gắng để làm cho /tmp.lock
) ..
Tóm lại, tôi cần phải lưu vào bộ nhớ cache urllib2
câu trả lời cho đĩa. Để thực hiện điều này, tôi cần truy cập vào một thư mục đã biết (tạo nó, nếu được yêu cầu), theo cách an toàn đa xử lý. Nó cần phải làm việc trên OS X, Linux và Windows.
Suy nghĩ? Giải pháp thay thế duy nhất tôi có thể nghĩ đến là viết lại mô đun bộ nhớ cache bằng cách sử dụng bộ nhớ SQLite3, chứ không phải là tệp.
Có thể! Tôi nghĩ về điều đó giống như tôi đang đọc lại câu hỏi, trước khi gửi nó .. Tôi đã thực hiện điều này (http://github.com/dbr/tvdb_api/blob/468d9f816373b14ef3a483fca07e031b69fa62f9/cache.py#L103-114), và sẽ nhận được người báo cáo lỗi để kiểm tra nó ngay. – dbr
Điều này dường như hoạt động hoàn hảo, cảm ơn! – dbr
@dbr: lưu ý rằng trên dòng 114, bạn muốn 'tăng e' vì nó đã là một thể hiện của' OSError'. http://github.com/dbr/tvdb_api/blob/468d9f816373b14ef3a483fca07e031b69fa62f9/cache.py#L114 – nosklo