оригинал (большая часть этого изменилась; см. Обновления ниже)
На основании некоторых предложений (спасибо!) Из Гленна Мейнарда и других, ярешил свернуть потомка Queue.Queue
, который реализует метод close
.Он доступен в виде примитива (без упаковки) модуль .Я уберу это немного и упакую должным образом, когда у меня будет немного больше времени.На данный момент модуль содержит только класс CloseableQueue
и класс исключений Closed
.Я планирую расширить его, включив в него также подклассы Queue.LifoQueue
и Queue.PriorityQueue
.
В настоящее время он находится в довольно предварительном состоянии, то есть, несмотря на то, что он проходит свой набор тестов, я нена самом деле использовал его для чего-либо еще.Ваш пробег может варьироваться.Я буду держать этот ответ обновленным с захватывающими новостями.
Класс CloseableQueue
немного отличается от предложения Гленна в том, что закрытие очереди предотвратит будущие put
с, но не предотвратит будущие get
с, покаочередь опустошена.Это имело для меня наибольшее значение;казалось, что функциональность для очистки очереди может быть добавлена как отдельный миксин *, который будет ортогонален функциональности закрываемости.Таким образом, в основном с CloseableQueue
, закрывая очередь, вы указываете, что последний элемент был put
.Также есть возможность сделать это атомарно, передав last=True
на последний put
вызов.Последующие вызовы put
и последующие вызовы get
после освобождения очереди, а также невыполненные заблокированные вызовы, соответствующие этим описаниям, вызовут исключение Closed
.
Это в основном полезно в ситуацияхгде один производитель генерирует данные для одного или нескольких потребителей, но это также может быть полезно для мульти-мультипроекта, где потребители ждут определенного товара или набора товаров.В частности, это не дает возможность определить, что все несколько производителей завершили производство.Получение этой работы повлекло бы за собой предоставление некоторого способа регистрации производителей (.open()
?), А также способа указать, что регистрация производителя сама закрыта.
Предложения и / или проверки кода весьма приветствуются.Я не написал много кода для параллелизма, но, надеюсь, набор тестов достаточно тщательный, чтобы тот факт, что код проходит его, является показателем качества кода, а не его отсутствия.Мне удалось повторно использовать код из набора тестов модуля Queue: сам файл включен в этот модуль и используется в качестве основы для различных подклассов и процедур, включая регрессионное тестирование.Это, вероятно (надеюсь) помогло избежать полной неумелости в отделе тестирования.Сам код просто переопределяет Queue.get
и Queue.put
с довольно минимальными изменениями и добавляет методы close
и closed
.
Я вроде как намеренно избегал использования любой новой фантазии, такой как контекстменеджеры как в самом коде, так и в наборе тестов, чтобы сохранить код как обратно совместимый, так же как и сам модуль Queue, который действительно значительно обратный.Возможно, в какой-то момент я добавлю методы __enter__
и __exit__
;в противном случае функция закрытия для contextlib должна быть применима к экземпляру CloseableQueue.
*: Здесь я свободно использую термин «миксин».Так как классы модуля Queue
выполнены в старом стиле, миксины необходимо будет смешивать с использованием функций фабрики классов;применяются некоторые ограничения;предложение void там, где это запрещено Гвидо.
update
Модуль CloseableQueue теперь предоставляет классы CloseableLifoQueue
и CloseablePriorityQueue
.Я также добавил несколько вспомогательных функций для поддержки итерации.Еще нужно переделать его как надлежащий пакет.Есть функция фабрики классов, которая позволяет удобно создавать подклассы для других Queue.Queue
классов.
update 2
CloseableQueue
теперь доступно через PyPI , например, с
$ easy_install CloseableQueue
Комментарии и критика приветствуются, особенно от анонимного downvoter этого ответа.