2010-02-20 29 views
12

Mam dwa wątki, jeden zapisujący do pliku, a drugi, który okresowo przenosi plik do innej lokalizacji. Napisy zawsze wywołują open przed napisaniem wiadomości i wywołują close po napisaniu wiadomości. Ruchomy używa shutil.move, aby wykonać ruch.Python wielu wątków uzyskujących dostęp do tego samego pliku

Widzę, że po wykonaniu pierwszego ruchu scenarzysta nie może już pisać do pliku, tzn. Rozmiar pliku zawsze wynosi 0 po pierwszym ruchu. czy robię coś źle?

Odpowiedz

25

Blokowanie jest możliwym rozwiązaniem, ale preferuję ogólną architekturę obsługi każdego zewnętrznego zasobu (w tym pliku) pojedynczym, osobnym wątkiem. Inne wątki wysyłają żądania pracy do dedykowanego wątku na instancję Queue.Queue (i dostarczają osobną kolejkę jako część parametrów żądania pracy, jeśli potrzebują wyniku), dedykowany wątek spędza większość czasu czekając na .get na tym kolejka, a gdy tylko otrzyma żądanie, uruchamia się i wykonuje je (i jeśli to konieczne, zwraca wyniki w kolejce przekazanej).

Podałem szczegółowe przykłady tego podejścia, np. w "Python in a Nutshell". Kolejka Pythona jest wewnętrznie bezpieczna dla wątków i ogromnie upraszcza Twoje życie.

Zaletą tej architektury jest to, że przekłada się ona płynnie na multiprocessing, jeśli i kiedy zdecydujesz się na zamianę pracy na oddzielny proces zamiast na osobny wątek (np. W celu wykorzystania wielu rdzeni) - multiprocessing zapewnia własną workalike Queue wpisz, aby takie przejście gładkie jak jedwab ;-).

+0

Jeśli piszę biblioteka, która powinna być bezpieczna dla wątków, ale nie zawsze jest używana w wątkach. Czy powinienem przyjąć takie podejście, czy spojrzeć na zamek? Nie jestem pewien, czy moja biblioteka powinna tworzyć nowe wątki, jeśli jest używany tylko jeden wątek. Jakie jest najlepsze rozwiązanie dla zmiennej liczby wątków, które mogą być jednym? –

7

Kiedy dwa wątki mają dostęp do tych samych zasobów, zdarzają się dziwne rzeczy. Aby tego uniknąć, zawsze blokuj zasób. Python ma do tego wygodny threading.Lock, a także kilka innych narzędzi (patrz dokumentacja modułu threading).

4

Wyjazd http://www.evanfosmark.com/2009/01/cross-platform-file-locking-support-in-python/

Można użyć prostego zamka z jego kodem, jak napisane przez Evan Fosmark w starszym StackOverflow pytanie:

from filelock import FileLock 

with FileLock("myfile.txt"): 
    # work with the file as it is now locked 
    print("Lock acquired.") 

jeden z bardziej eleganckich bibliotek jakie kiedykolwiek widziałem .

+0

czy jesteś pewien, że można to w rzeczywistości połączyć z przenoszeniem plików? –

+3

Kod Evan Fosmark dotyczy synchronizacji wielu * procesów *, a nie * wątków *. Zgodnie z sugestią Eli'ego użyłbym 'threading.Lock' lub' threading.RLock'. –

+0

Jako kontynuacja, link w tym poście nie działa. Za [odpowiedź Evana na powiązane pytanie] (http://stackoverflow.com/a/498505/760905) można również znaleźć kod na https://github.com/dmfrey/FileLock – MartyMacGyver

Powiązane problemy