Задать вопрос

Эффективная многопоточность в python?

Нужна многопоточность на скриптовом языке - пробовал pthreads для php 7, но не смотря на заявления разработчиков, все работает криво и беспричинно вылетает. Поэтому смотрю в сторону python (а есть ли альтернативы?), но то тут то там пишут что многопоточность в нем реализована так, что многопоточные приложения уступают обычным и что там есть какие-то проблемы с локами и синхронизацией. Так ли это? Опыт многопоточности в питоне небольшой - простые качалки файлов на с помощью thread, но там, я так понимаю есть более удобные и мощные инструменты. Собственно вопрос - че там с многопоточностью и какие модули лучше всего юзать? Зачади: парсинг веб-страниц и занесение данных в бд. Спасибо!
  • Вопрос задан
  • 4308 просмотров
Подписаться 17 Оценить Комментировать
Пригласить эксперта
Ответы на вопрос 7
dimonchik2013
@dimonchik2013
non progredi est regredi
asyncio решит все проблемы (если освоите, конечно )) )

если как в ПХП - смотрите, например,
toly.github.io/blog/2014/02/13/parallelism-in-one-line

но aiohttp для парсинга повеселее будет

кстати, Scrapy портировали на 3й Питон уже, но сами же говорят что сыроват

касаемо мультипоточности, вот пример кода:
if __name__ == '__main__':
    freeze_support()

    pool = Pool(processes=8)
    names = pool.imap_unordered(extract, glob.iglob(GLOBDIR), chunksize=1000)
    for name in names:
        extract(name)


можете поискать по кускам примеры применения

это винда, поэтому freeze_support(), в линухе еще проще
также (processes=8) не равно числу ядер (их 12), подбирается экспериментально от загруза проца, что в win что в lin

glob.iglob(GLOBDIR) читает список файлов по маске, поскольку это итератор, а для пула нужно конкретное конечное число, используется параметр chunksize=1000

функция extract(name) расжимает файл по адресу name, парсит его lxml и вносит поля в базу, такая комбинация грузит проц на 60-80%, когда в один поток - 9-12%
Ответ написан
@kazmiruk
Что ж все так фигово читают вопрос. Все ответы выше никак не относятся к многопоточности. В питоне лучше вообще забыть что есть такое понятие "многопоточность", не ту технологию Вы выбираете для этого (хотя есть, конечно, pypy, но не в курсе на каком этапе там все. Также есть вариант с использованием процессов, но по мне это больше костыль). А в плане решения проблемы парсинга - да, можно заюзать асинхронность, но при этом будет использоваться один поток.
Ответ написан
abyrkov
@abyrkov
JavaScripter
Да хоть Node.js
Ответ написан
Комментировать
sim3x
@sim3x
Парсер сложно сделать параллельным
Паука - можно, но смысла нет

Общепризнанный паук на питоне scrapy.org
Ответ написан
nikolay_karelin
@nikolay_karelin
Ведущий разработчик, пишу на Python, Tcl, Matlab
Когда разговор заходит о многопоточности, то нужно сразу отметить, какие типы задач интересуют.

Если речь идет о CPU-bound задачах, и надо нагрузить многоядерный процессор, то да GIL мешает (даже запрещает), и в Python надо компилировать расширение или использовать несколько процессов.

Если же дело в IO-bound - это практически все задачки связянные с сетью, включая веб, - то, как правило, блокирующая операция ожидания ответа от сети освобождает GIL и можно спокойно использовать многопоточность.

Другое дело, что сейчас многие советуют использовать именно асинхронные фреймворки (тот же asyncio), которые для сетевых задач дают гораздо лучшую производительность, чем нативные потоки (хотя, вроде, greenlets еще лучше).
Ответ написан
Padreramnt
@Padreramnt
Padreramnt
Здравствуйте, изнините за ответ вопросом: а Вам необходимо использовать скриптовые языки? Если да, то лушче подойдет python, там в коробке есть библиотека: multiprocessing (ну или как-то так, точно не помню, давно это было), собственно она опасная, вызов ее функций ограничивается главный циклом:
if __name__ == "__main__":
    вот тут вызываем

соственно это настоящая многопоточность, ибо она опходит GIL (Global Interpreter Lock)
вся загвоздка GIL в том, что в его понятии поток - есть очередь.
Например: у нас есть 3 потока, каджый выпоняет определенную функцию, для каждого свою; выполняется 1 поток, в нем выполняется, нарпимер, 100 операций, потом особая метка GIL переходит ко второму потоку, первый замораживается. Суть в том, что у кого метка GIL, тот и выполняется, остальные ждут метку GIL.
Если вам необходимо просто что-то сделать многопоточно, не зависимо от зяыка.
как вариант, можете посмотреть на C++, тут 3 варианта: MPI (есть билд для питона, можно запустить на кластере), PThread - ООП потоки, достаточно удобна в использовании, главное не залочить все потоки по кругу, в общем, внимательнее, OpenMP - няшечка компилятор сам все распаралелит, главное сказать какие циклы сделать паралельными, присутсвует в g++ и msvs2010+ (компилятор в Visual Studio).
Если вся проблема в том, чтобы запускать программу на любой платформе, то Вам могут подойти Qt и Mono
Ответ написан
@artem78
Я для многопоточного парсинга использую perl + модуль threads. С асинхронностью как-то не подружился да и для парсера разбор DOM (а не ожидание сети) отнимает основную часть времени.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

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