Muszę zablokować plik do pisania w Pythonie. Będzie dostępny z wielu procesów Pythona jednocześnie. Znalazłem kilka rozwiązań online, ale większość z nich nie spełnia moich oczekiwań, ponieważ często są one oparte tylko na Uniksie lub Windowsie.
python
file-locking
Evan Fosmark
źródło
źródło
W tym miejscu znajduje się wieloplatformowy moduł blokowania plików: Portalocker
Chociaż, jak mówi Kevin, zapisywanie do pliku z wielu procesów jednocześnie jest czymś, czego chcesz uniknąć, jeśli to w ogóle możliwe.
Jeśli możesz umieścić problem w bazie danych, możesz użyć SQLite. Obsługuje równoczesny dostęp i obsługuje własne blokowanie.
źródło
Inne rozwiązania przytaczają wiele zewnętrznych baz kodu. Jeśli wolisz zrobić to sam, oto kod dla rozwiązania wieloplatformowego, które wykorzystuje odpowiednie narzędzia do blokowania plików w systemach Linux / DOS.
Teraz
AtomicOpen
może być używany wwith
bloku, w którym normalnie używałbyśopen
instrukcji.OSTRZEŻENIE: Jeśli uruchamianie w systemie Windows i Python ulega awarii przed wywołaniem wyjścia , nie jestem pewien, jakie byłoby zachowanie blokady.
OSTRZEŻENIE: Podana tu blokada jest zalecana, a nie bezwzględna. Wszystkie potencjalnie konkurujące procesy muszą używać klasy „AtomicOpen”.
źródło
unlock_file
plik wfcntl
systemie Linux nie powinien dzwonić ponownie zLOCK_UN
flagą?__exit__
tobieclose
poza zamkiem pounlock_file
. Uważam, że środowisko wykonawcze może opróżniać (tj. Zapisywać) dane podczasclose
. Uważam, że należyflush
ifsync
pod zamkiem, aby upewnić się, że żadne dodatkowe dane nie zostaną zapisane poza zamkiem podczasclose
.flush
ifsync
. Dodałem dwie linie, które zasugerowałeś, zanim zadzwoniszunlock
. Ponownie przetestowałem i stan wyścigu wydaje się być rozwiązany.Wolę lockfile - niezależne od platformy blokowanie plików
źródło
Szukałem kilku rozwiązań, aby to zrobić, i mój wybór to oslo.concurrency
Jest potężny i stosunkowo dobrze udokumentowany. Opiera się na elementach złącznych.
Inne rozwiązania:
źródło
filelock
(ostatnie wydanie: 18 maja 2019 w momencie komentowania)Blokowanie zależy od platformy i urządzenia, ale ogólnie masz kilka opcji:
W przypadku wszystkich tych metod będziesz musiał użyć techniki blokowania spinu (ponowna próba po awarii) w celu uzyskania i przetestowania blokady. To pozostawia małe okno na błędną synchronizację, ale generalnie jest na tyle małe, że nie stanowi poważnego problemu.
Jeśli szukasz rozwiązania wieloplatformowego, lepiej zaloguj się do innego systemu za pomocą innego mechanizmu (następną najlepszą rzeczą jest powyższa technika NFS).
Zauważ, że sqlite podlega tym samym ograniczeniom w systemie plików NFS, co normalne pliki, więc nie możesz pisać do bazy danych sqlite w udziale sieciowym i uzyskiwać synchronizacji za darmo.
źródło
os.rename
jest teraz atomowa w Win32 od Pythona 3.3: bugs.python.org/issue8828Koordynacja dostępu do pojedynczego pliku na poziomie systemu operacyjnego jest pełna różnego rodzaju problemów, których prawdopodobnie nie chcesz rozwiązać.
Najlepiej jest mieć oddzielny proces, który koordynuje dostęp do odczytu / zapisu do tego pliku.
źródło
flock
. Podejście „rzuć własne muteksy i proces demona, aby nimi zarządzać” wydaje się być raczej ekstremalnym i skomplikowanym podejściem do rozwiązania ... problem, o którym tak naprawdę nam nie powiedziałeś, ale po prostu sugerowałeś, że istnieje.Blokowanie pliku jest zwykle operacją specyficzną dla platformy, więc może być konieczne zezwolenie na uruchomienie w różnych systemach operacyjnych. Na przykład:
źródło
Pracowałem nad taką sytuacją, w której uruchamiam wiele kopii tego samego programu z tego samego katalogu / folderu i rejestruję błędy. Moje podejście polegało na zapisaniu „pliku blokady” na dysku przed otwarciem pliku dziennika. Program sprawdza obecność „pliku blokady” przed kontynuowaniem i czeka na swoją kolej, jeśli „plik blokady” istnieje.
Oto kod:
EDYTUJ --- Po przemyśleniu niektórych komentarzy dotyczących nieaktualnych blokad powyżej, zredagowałem kod, aby dodać sprawdzenie nieaktualności „pliku blokady”. Czas kilku tysięcy iteracji tej funkcji w moim systemie dał średnio 0,002066 ... sekund tuż przed:
zaraz po:
więc doszedłem do wniosku, że zacznę od 5 razy większej ilości, aby wskazać nieaktualność i monitorować sytuację pod kątem problemów.
Ponadto, pracując z synchronizacją, zdałem sobie sprawę, że mam kawałek kodu, który nie był naprawdę potrzebny:
które miałem natychmiast po otwartym oświadczeniu, więc usunąłem go w tej edycji.
źródło
Aby dodać do odpowiedzi Evana Fossmarka , oto przykład użycia blokady filelock :
Każdy kod w
with lock:
bloku jest bezpieczny dla wątków, co oznacza, że zostanie zakończony, zanim inny proces uzyska dostęp do pliku.źródło
Scenariusz jest tak: użytkownik zażąda plik do zrobienia czegoś. Następnie, jeśli użytkownik ponownie wyśle to samo żądanie, informuje użytkownika, że drugie żądanie nie zostanie wykonane, dopóki pierwsze żądanie nie zakończy się. Dlatego używam mechanizmu blokującego, aby rozwiązać ten problem.
Oto mój działający kod:
źródło
Znalazłem prostą i działającą (!) Implementację z grizzled-python.
Proste użycie os.open (..., O_EXCL) + os.close () nie działało w systemie Windows.
źródło
Pylocker może być bardzo przydatny. Może być używany do blokowania pliku lub ogólnie do blokowania mechanizmów i może być dostępny z wielu procesów Pythona jednocześnie.
Jeśli chcesz po prostu zablokować plik, oto jak to działa:
źródło