Подтвердить что ты не робот

Несколько потоков Python, обращающихся к одному файлу

У меня есть два потока, один из которых записывается в файл, а другой - периодически перемещает файл в другое место. Запись всегда вызывает open перед записью сообщения и вызывает close после записи сообщения. Для выполнения перемещения движок использует shutil.move.

Я вижу, что после того, как первый шаг сделан, писатель больше не может писать в файл, т.е. размер файла всегда равен 0 после первого перемещения. Я что-то делаю неправильно?

4b9b3361

Ответ 1

Блокировка - это возможное решение, но я предпочитаю общую архитектуру наличия каждого внешнего ресурса (включая файл), который обрабатывается одним отдельным потоком. Другие потоки отправляют рабочие запросы в выделенный поток на экземпляр Queue.Queue (и предоставляют отдельную отдельную очередь в качестве части параметров запроса на работу если они нуждаются в возврате результата), выделенный поток тратит большую часть своего времени на .get в этой очереди, и всякий раз, когда он получает запросы, выполняется и выполняет его (и при необходимости возвращает результаты в очередь передачи).

Я привел подробные примеры этого подхода, например. в "Python в двух словах". Очередь Python по своей сути является потокобезопасной и чрезвычайно упрощает вашу жизнь.

Среди преимуществ этой архитектуры заключается в том, что она плавно переходит на multiprocessing, если и когда вы решите переключить некоторую работу на отдельный процесс вместо отдельного потока (например, для использования нескольких ядер) - multiprocessing предоставляет свой собственный рабочий тип Queue, чтобы сделать такой переход гладким, как шелк; -).

Ответ 2

Когда два потока обращаются к тем же ресурсам, происходят странные вещи. Чтобы этого избежать, всегда блокируйте ресурс. Для этого у Python есть удобный threading.Lock, а также некоторые другие инструменты (см. Документацию модуля threading).

Ответ 3

Отъезд http://www.evanfosmark.com/2009/01/cross-platform-file-locking-support-in-python/

Вы можете использовать простую блокировку с его кодом, как написано Эван Фосмарк в более старом вопросе StackOverflow:

from filelock import FileLock

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

Одна из самых элегантных библиотек, которые я когда-либо видел.