Исходный код и issue-трекер на github
Пакет на PyPI
Документация (en)
Идея взята из презентации Using futures for async GUI programming in Python 3.3
Пример обработчика нажатия кнопки
@engine.async def on_button_click(self, *args): self.status_label.setText("Downloading image...") # Run single task in separate thread image_data = yield Task(self.load_url, "http://www.google.com/images/srpr/logo4w.png") pixmap = QtGui.QPixmap.fromImage(QtGui.QImage.fromData(image_data)) self.image_label.setPixmap(pixmap) self.status_label.setText("Downloading pages...") urls = ['http://www.google.com', 'http://www.yandex.ru', 'http://www.python.org'] # Run multiple task simultaneously in thread pool pages = yield [Task(self.load_url, url) for url in urls] self.status_label.setText("Done") avg_size = sum(map(len, pages)) / len(pages) self.result_label.setText("Average page size: %s" % avg_size)
Так как загрузка данных из сети может занять некоторое время и сделать интерфейс неотзывчивым, эти операции выполнены в отдельных потоках.
При этом код выглядит последовательно, а обновления интерфейса происходят в потоке GUI.
Возможности и особенности:
- Поддержка Python 2.7+ (требуется futures), и Python 3+
- Поддержка PyQt4/PySide, Tk, Wx, Gtk. Просто добавить другие тулкиты
- Можно запускать задачи в Thread'ах, Process'ах, Greenlet'ах (требуется gevent)
- Запуск нескольких задач одновременно
- Обработка ошибок, как в коде без потокв
- Покрытие тестами
В отличие от библиотеки из презентации, async_gui нацелена на совместимость с Python 2.7-3+, поэтому не использует yield from и tulip.
Данный релиз является предварительным, возможны изменения API.