Поточная обработка в [закрытом] Python

Можно использовать загрузчик Flash как SWFupload, чтобы сделать это, также.

76
задан Makoto 18 May 2015 в 01:22
поделиться

7 ответов

В порядке возрастания сложности:

Используйте модуль потоковой передачи

Плюсы:

  • Любую функцию (фактически любую вызываемую) действительно легко запустить в ее собственный поток.
  • Совместное использование данных, если не так просто (блокировки никогда не бывает легким :), в наименее простой.

Минусы:

  • Как упоминалось Юргеном потоки Python не могут одновременно обращаться к состоянию в интерпретаторе (есть одна большая блокировка, печально известная Глобальная блокировка интерпретатора .) На практике это означает, что потоки полезны для задач, связанных с вводом-выводом (сеть, запись на диск и т. Д.), Но совсем не полезны для выполнения параллельных вычислений.

Используйте многопроцессорность module

В простом случае это выглядит точно так же, как при использовании threading , за исключением того, что каждая задача запускается в собственном процессе, а не в собственном потоке. (Почти буквально: если взять пример Эли и заменить threading на multiprocessing , Thread , на Process ] , и Queue (модуль) с multiprocessing.Queue , он должен работать нормально.)

Плюсы:

  • Фактический параллелизм для всех задач (без глобальной блокировки интерпретатора).
  • Масштабируется до нескольких процессоров, может даже масштабироваться до нескольких машин .

Минусы:

  • Процессы медленнее, чем потоки.
  • Обмен данными между процессами сложнее, чем с потоками.
  • ] Неявно разделяемая память не используется. Вы должны либо явно поделиться им, либо вам нужно собрать переменные и отправлять их туда и обратно. Это безопаснее, но сложнее. (Если это имеет все большее значение, кажется, что разработчики Python подталкивают людей в этом направлении.)

Используйте модель событий, такую ​​как Twisted

Плюсы:

  • Вы получаете чрезвычайно точный контроль над приоритетом, над тем, что выполняется, когда.

Минусы:

  • Даже с хорошей библиотекой асинхронное программирование обычно сложнее, чем многопоточное, сложное как с точки зрения понимания того, что должно происходить, так и с точки зрения отладки того, что на самом деле происходит.

Во всех всех случаях я предполагаю, что вы уже понимаете многие из проблемы, связанные с многозадачностью, особенно сложный вопрос о том, как разделять данные между задачами. Если по какой-то причине вы не знаете, когда и как использовать блокировки и условия, вам следует начать с них. Код многозадачности полон тонкостей и подводных камней, и действительно лучше иметь хорошее понимание концепций, прежде чем начать.

m при условии, что вы уже понимаете многие проблемы, связанные с многозадачностью, в частности, сложный вопрос о том, как обмениваться данными между задачами. Если по какой-то причине вы не знаете, когда и как использовать блокировки и условия, вам следует начать с них. Код многозадачности полон тонкостей и подводных камней, и действительно лучше иметь хорошее понимание концепций, прежде чем начинать.

m при условии, что вы уже понимаете многие проблемы, связанные с многозадачностью, в частности, сложный вопрос о том, как разделять данные между задачами. Если по какой-то причине вы не знаете, когда и как использовать блокировки и условия, вам следует начать с них. Код многозадачности полон тонкостей и подводных камней, и действительно лучше иметь хорошее понимание концепций, прежде чем начинать.

115
ответ дан 24 November 2019 в 11:04
поделиться

Это зависит от того, что вы пытаетесь сделать, но я частично к использованию модуля threading в стандартной библиотеке, потому что он позволяет легко взять любую функцию и просто запустить ее в отдельном потоке.

from threading import Thread

def f():
    ...

def g(arg1, arg2, arg3=None):
    ....

Thread(target=f).start()
Thread(target=g, args=[5, 6], kwargs={"arg3": 12}).start()

И так далее. У меня часто бывает установка производителя / потребителя с использованием синхронизированной очереди, предоставляемой модулем Queue

from Queue import Queue
from threading import Thread

q = Queue()
def consumer():
    while True:
        print sum(q.get())

def producer(data_source):
    for line in data_source:
        q.put( map(int, line.split()) )

Thread(target=producer, args=[SOME_INPUT_FILE_OR_SOMETHING]).start()
for i in range(10):
    Thread(target=consumer).start()
20
ответ дан 24 November 2019 в 11:04
поделиться

Kamaelia - это среда Python для создания приложений с большим количеством взаимодействующих процессов.

(источник: kamaelia.org ) Kamaelia - Concurrency made полезно, весело

В Kamaelia вы строите системы из простых компонентов, которые взаимодействуют друг с другом . Это ускоряет разработку, значительно упрощает обслуживание, а также означает, что вы создаете естественно параллельное программное обеспечение . Он предназначен для любого разработчика , включая новичков. Это еще и забавно :)

Какие системы? Сетевые серверы, клиенты, настольные приложения, игры на основе pygame, системы перекодирования и конвейеры, системы цифрового телевидения, средства устранения спама, обучающие инструменты и многое другое :)

Вот видео с Pycon 2009.

Простой параллелизм с Камаэлией - Часть 1 (59:08)
Легкий параллелизм с Камаэлией - Часть 2 (18:15)

13
ответ дан 24 November 2019 в 11:04
поделиться

Я бы использовал микропотоки (тасклеты) Stackless Python, если бы мне вообще пришлось использовать потоки.

Вся онлайн-игра (массовая многопользовательская) построена вокруг Stackless и его принцип многопоточности - поскольку оригинал просто слишком медленный из-за массового многопользовательского режима игры.

Потоки в CPython широко не приветствуются. Одна из причин - GIL - глобальная блокировка интерпретатора, которая сериализует потоки для многих частей выполнения. По моему опыту, таким способом действительно сложно создавать быстрые приложения.

3
ответ дан 24 November 2019 в 11:04
поделиться

Если вы действительно хотите запачкать руки, вы можете попробовать , используя генераторы для подделки сопрограмм . Вероятно, это не самый эффективный с точки зрения выполняемой работы, но сопрограммы предлагают вам очень точный контроль совместной многозадачности, а не упреждающую многозадачность, которую вы найдете в другом месте.

Одно из преимуществ, которое вы обнаружите, заключается в том, что в целом вам не понадобятся блокировки или мьютексы при использовании совместной многозадачности, но более важным преимуществом для меня была почти нулевая скорость переключения между «потоками». Конечно, говорят, что Stackless Python также очень хорош для этого; а затем есть Erlang, если он не , чтобы быть Python.

Вероятно, самым большим недостатком совместной многозадачности является общее отсутствие обходного пути для блокировки ввода-вывода. А в поддельных сопрограммах вы также столкнетесь с проблемой, что вы не можете переключать «потоки» из чего-либо, кроме верхнего уровня стека внутри потока.

После того, как вы создали даже немного сложное приложение с поддельным сопрограмм, вы действительно начнете ценить работу, которая входит в планирование процессов на уровне ОС.

2
ответ дан 24 November 2019 в 11:04
поделиться

Что касается Камаэлии, приведенный выше ответ на самом деле не охватывает здесь преимущества. Подход Камаэлии обеспечивает унифицированный интерфейс, который прагматичен и не идеален, для работы с потоками, генераторами и процессами в единой системе для параллелизма.

По сути, он представляет собой метафору работающего объекта, у которого есть входящие и исходящие ящики. Вы отправляете сообщения в ящики исходящих сообщений, и когда они связаны вместе, сообщения перетекают из ящиков исходящих в ящики входящих. Эта метафора / API остается неизменной независимо от того, используете ли вы генераторы, потоки или процессы или разговариваете с другими системами.

«Неидеальная» часть связана с тем, что синтаксический сахар еще не добавлен для ящиков входящих и исходящих (хотя это обсуждается) - в системе делается упор на безопасность / удобство использования.

В приведенном выше примере производителя-потребителя, использующего голую потоковую передачу, в Kamaelia это становится следующим:

Pipeline(Producer(), Consumer() )

В этом примере не имеет значения, являются ли они потоковыми компонентами или нет, единственная разница между ними с точки зрения использования заключается в том, что базовый класс для компонента. Компоненты генератора взаимодействуют с помощью списков, потоковые компоненты с помощью Queue.Queues и процессов на основе os.pipes.

Причина, лежащая в основе такого подхода, состоит в том, чтобы усложнить отладку ошибок. При многопоточности или любом параллельном использовании разделяемой памяти проблема номер один, с которой вы сталкиваетесь, - это случайное нарушение обновления общих данных. Используя передачу сообщений, вы устраняете один класс ошибок.

Если вы везде используете голые потоки и блокировки, вы обычно работаете в предположении, что когда вы пишете код, который выиграете » не делаю ошибок. Хотя мы все к этому стремимся, такое случается очень редко. Объединив поведение блокировки в одном месте, вы упростите то, где что-то может пойти не так. (Обработчики контекста помогают, но не помогают при случайных обновлениях вне обработчика контекста)

Очевидно, что не каждый фрагмент кода может быть написан как передача сообщений и общий стиль, поэтому в Kamaelia также есть простая программная транзакционная память (STM) , что является действительно изящной идеей с неприятным названием - это больше похоже на контроль версий для переменных - т.е. проверить некоторые переменные, обновить их и зафиксировать обратно. Если вы столкнулись с конфликтом, промойте его и повторите.

Соответствующие ссылки:

В любом случае, я надеюсь, что это полезный ответ. FWIW, основная причина установки Kamaelia - сделать параллелизм более безопасным и простым в использовании в системах Python, без виляния хвостом собаки. (т.е. большое ведро компонентов

. Я могу понять, почему другой ответ Kamaelia был изменен, поскольку даже для меня он больше похож на рекламу, чем на ответ. Как автору Kamaelia приятно видеть энтузиазм, хотя я надеюсь, что это содержит немного более релевантное содержание: -)

И это мой способ сказать, пожалуйста, примите предостережение, что этот ответ по определению предвзят, но для меня цель Камаэлии - попытаться обернуть то, что является лучшей практикой ИМО. Я предлагаю попробовать несколько систем и посмотреть, какая из них вам подходит. (также, если это не подходит для переполнения стека, извините - я новичок в этом форуме: -)

Настройка заключается в том, чтобы сделать параллелизм более безопасным и простым в использовании в системах Python, чтобы хвост не вилял собакой. (т.е. большое ведро компонентов

. Я могу понять, почему другой ответ Kamaelia был изменен, поскольку даже для меня он больше похож на рекламу, чем на ответ. Как автору Kamaelia приятно видеть энтузиазм, хотя я надеюсь, что это содержит немного более релевантное содержание: -)

И это мой способ сказать, пожалуйста, примите предостережение, что этот ответ по определению предвзят, но для меня цель Камаэлии - попытаться обернуть то, что является лучшей практикой ИМО. Я бы посоветовал опробовать несколько систем и посмотреть, какая из них вам подходит. (также, если это не подходит для переполнения стека, извините - я новичок в этом форуме: -)

Настройка заключается в том, чтобы сделать параллелизм более безопасным и простым в использовании в системах Python, чтобы хвост не вилял собакой. (т.е. большое ведро компонентов

. Я могу понять, почему другой ответ Kamaelia был изменен, поскольку даже для меня он больше похож на рекламу, чем на ответ. Как автору Kamaelia приятно видеть энтузиазм, хотя я надеюсь, что это содержит немного более релевантное содержание: -)

И это мой способ сказать, пожалуйста, примите предостережение, что этот ответ по определению предвзят, но для меня цель Камаэлии - попытаться обернуть то, что является лучшей практикой ИМО. Я предлагаю попробовать несколько систем и посмотреть, какая из них вам подходит. (также, если это не подходит для переполнения стека, извините - я новичок в этом форуме: -)

(т.е. большое ведро компонентов

. Я могу понять, почему другой ответ Kamaelia был изменен, поскольку даже для меня он больше похож на рекламу, чем на ответ. Как автору Kamaelia приятно видеть энтузиазм, хотя я надеюсь, что это содержит немного более релевантное содержание: -)

И это мой способ сказать, пожалуйста, примите предостережение, что этот ответ по определению предвзят, но для меня цель Камаэлии - попытаться обернуть то, что является лучшей практикой ИМО. Я бы посоветовал опробовать несколько систем и посмотреть, какая из них вам подходит. (также, если это не подходит для переполнения стека, извините - я новичок в этом форуме: -)

(т.е. большое ведро компонентов

. Я могу понять, почему другой ответ Kamaelia был изменен, поскольку даже для меня он больше похож на рекламу, чем на ответ. Как автору Kamaelia приятно видеть энтузиазм, хотя я надеюсь, что это содержит немного более релевантное содержание: -)

И это мой способ сказать, пожалуйста, примите предостережение, что этот ответ по определению предвзят, но для меня цель Камаэлии - попытаться обернуть то, что является лучшей практикой ИМО. Я предлагаю попробовать несколько систем и посмотреть, какая из них вам подходит. (также, если это не подходит для переполнения стека, извините - я новичок в этом форуме: -)

-)

И это мой способ сказать, пожалуйста, примите предостережение, что этот ответ по определению предвзят, но для меня цель Камаэлии - попытаться обернуть то, что является лучшей практикой ИМО. Я предлагаю попробовать несколько систем и посмотреть, какая из них вам подходит. (также, если это не подходит для переполнения стека, извините - я новичок в этом форуме: -)

-)

И это мой способ сказать, пожалуйста, примите предостережение, что этот ответ по определению предвзят, но для меня цель Камаэлии - попытаться обернуть то, что является лучшей практикой ИМО. Я бы посоветовал опробовать несколько систем и посмотреть, какая из них вам подходит. (также, если это не подходит для переполнения стека, извините - я новичок в этом форуме: -)

6
ответ дан 24 November 2019 в 11:04
поделиться

Думаю, если вы говорите только о дюжине, все будет в порядке. Я работаю над приложением со 100+ сборками, и это очень мучительно.

Если у вас нет способа управления зависимостями - зная, что выйдет из строя, если вы измените сборку X, у вас проблемы.

Одна «приятная» проблема, с которой я столкнулся, - это когда сборка A ссылается сборки B, C и B ссылаются на V1 сборки D, в то время как C ссылается на V2 сборки D. («Скрученный алмаз» было бы неплохим названием для этого)

Если вы хотите иметь автоматизированную сборку, вы собираетесь получать удовольствие от поддержки сценария сборки (который нужно будет строить в обратном порядке зависимостей) или иметь `` одно решение, чтобы управлять ими всеми '', Думаю, ответ на ваш вопрос очень сильно зависит от семантики ваших сборок. Могут ли разные приложения использовать одну сборку? Хотите иметь возможность обновлять сборки для обоих приложений по отдельности? Вы собираетесь использовать GAC? Или скопировать сборки рядом с исполняемыми?

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

Выделите специализированный поток каждому ресурсу, который вы обычно думаете защищать блокировками: изменяемая структура данных или связная группа из них, соединение с внешним процессом ( DB, сервер XMLRPC и т. Д.), Внешний файл и т. Д. И т. Д. Получите небольшой пул потоков, предназначенный для задач общего назначения, которые не имеют или не нуждаются в выделенном ресурсе такого типа - нет порождают потоки по мере необходимости, иначе накладные расходы, связанные с переключением потоков, сокрушат вас.

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

Каждый выделенный поток, управляющий одним ресурсом (или небольшим связным набором ресурсов), прослушивает запросы в конкретном экземпляре Queue.Queue. Потоки в пуле ждут в одной общей очереди Queue.Queue (Очередь полностью потокобезопасна, и не подведет вас в этом).

Потоки, которым просто нужно поставить в очередь запрос в некоторой очереди (общая или посвященный) сделать это, не дожидаясь результатов, и двигаться дальше. Потоки, которым в конечном итоге ДЕЙСТВИТЕЛЬНО требуется результат или подтверждение для очереди запросов, ставят пару (запрос, очередь получения) с экземпляром Queue. Очередь, которую они только что создали, и в конечном итоге, когда для продолжения требуется ответ или подтверждение, они получают (ожидают) из своей очереди получения. Убедитесь, что вы готовы получать ответы об ошибках, а также реальные ответы или подтверждения ( deferred Twisted отлично подходят для организации такого рода структурированных ответов, кстати!)

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

102
ответ дан 24 November 2019 в 11:04
поделиться
Другие вопросы по тегам:

Похожие вопросы: