LINUX.ORG.RU

Перевод статьи «Основы работы с потоками в Python»


0

0

Перевод статьи Basic Threading in Python (автор Peyton McCullough).

Если вы желаете, чтобы ваше приложение выполняло несколько задач в одно и то же время, то можете воспользоваться потоками (threads). Python может работать с потоками, но много разработчиков находят программирование потоков очень сложным.

>>> читать статью

anonymous

Проверено: anonymous_incognito ()

Ответ на: комментарий от r

> Но вообще я расшифровал что там написано - за такое яйца отрывать надо. До гланд.

Этот классический race conditions из *статьи* ??? А я уж думал плохие слова говорить. Впрочем если это учебный цикл, то весело дать такой пример, ат потом предложить вписать sleep(1) между принтами :)

sv75 ★★★★★
()
Ответ на: комментарий от makkintosh

>а в stackless все ещё интереснее. там переключение между тредами руками делается. Говорят так удобнее.

Это как в Windows 3.1x? :)

KRoN73 ★★★★★
()
Ответ на: комментарий от tailgunner

Ябы не сказал что threads такие сложные...

По поводу отспутов для задания логических блоков - это дело привычки так писать... Я например весь код оформляю так в любом языке для читаемости, мне это просто и этот принцип языка ABS (если я не ошибаюсь, но с такого языка подсмотрели форматирование) я прекрастно понимаю и считаю более логичным.

Все просто дело привычки :) см знаю людей которым проще и понятнее на асме чем на Си присать

Red_Lion
()

>Peyton

у них тоже есть падонки?

swar0g ★★★★
()
Ответ на: комментарий от the_moon

На самом деле, увжаемый, для любого мало-мальски распространенного языка есть style guide. При изучении любого языка стоит его почитать и следовать ему. Будь то Java Code Convention http://java.sun.com/docs/codeconv/ или Python Style Guide http://www.python.org/dev/peps/pep-0008/ . Так вот, в последнем написано:

>Indentation

> Use 4 spaces per indentation level.

> For really old code that you don't want to mess up, you can continue to use 8-space tabs.

parser ★★
()
Ответ на: комментарий от sv75

>Согласен. __init__ лучше избегать. С другой стороны, логика и единообразие есть.

а расскажите почему __init__ нужно избегать я, например, не знаю, может еще кто не знает, было бы интересно.

alt0v14 ★★★
()
Ответ на: комментарий от isden

>есть такая вещь, как целесообразность. имхо производительность веб сервера в такой реализации упадет ниже плинтуса...

сервер на select - одна из самых быстрых реализаций.

AVL2 ★★★★★
()
Ответ на: комментарий от anonymous

>Питоновские же треды плохи тем, что там GIL и пользы от них - чуть.

Сами питоновские треды еще ничего.

Куда хуже, что все расширения тоже должны быть safe-trhread. Например, pygtk очень долго был без подержки тредов вообще, потом глючил с ними страшно, а теперь работает с десятком костылей.

AVL2 ★★★★★
()
Ответ на: комментарий от Red_Lion

>Ябы не сказал что threads такие сложные...

Сами по себе - нет.

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

AVL2 ★★★★★
()
Ответ на: комментарий от alt0v14

>а расскажите почему __init__ нужно избегать я, например, не знаю, может еще кто не знает, было бы интересно.

+1

Ждем комментария ;)

Чем это вам конструкторы не угодили?

AVL2 ★★★★★
()

Multi Process, no GIL | Гвидо не может ошибаться ;)

Читайте Pythonmagazine.com за 10/2007

anonymous
()

А еще можно форкнуться по количеству процессоров и уже в форках плодить треды

Stiletto
()
Ответ на: комментарий от r

Вопрос на засыпку: чему будет равняться theVar по окончании программы? Хотя на одном процессоре можно ничего и не заметить. Лучше так: <pre> public class MyThread extends Thread { static int theVar = 1;

public void run() { try { for (int i = 0; i < 10000000; i ++) new Integer(i); System.out.println("This is thread " + theVar + " speaking."); System.out.println("Hello and good bye."); theVar = theVar + 1; } catch (Exception e) { } }

public static void main(String[] args) { for (int x = 0; x < 20; x++) new MyThread().start(); System.out.println("Main: theVar = " + theVar); } }

# java myTread Main: theVar = 1 This is thread 1 speaking. Hello and good bye. This is thread 2 speaking. Hello and good bye. This is thread 3 speaking. Hello and good bye. This is thread 3 speaking. Hello and good bye. This is thread 5 speaking. Hello and good bye. This is thread 6 speaking. Hello and good bye. This is thread 7 speaking. Hello and good bye. This is thread 8 speaking. Hello and good bye. This is thread 9 speaking. Hello and good bye. This is thread 10 speaking. This is thread 10 speaking. Hello and good bye. This is thread 10 speaking. Hello and good bye. Hello and good bye. This is thread 13 speaking. Hello and good bye. This is thread 14 speaking. Hello and good bye. This is thread 15 speaking. Hello and good bye. This is thread 14 speaking. Hello and good bye. This is thread 17 speaking. Hello and good bye. This is thread 18 speaking. Hello and good bye. This is thread 19 speaking. Hello and good bye. This is thread 20 speaking. Hello and good bye. </pre>

Плоховато у тебя со средами. Но суть уловил. Молодец :)

anonymous
()
Ответ на: комментарий от alt0v14

ну написал же <pre>
ах, там еще <Preformatted text> надо было выбрать
странная тут лента комментариев какая то...

anonymous
()
Ответ на: комментарий от anonymous

>Плоховато у тебя со средами. Но суть уловил. Молодец :)

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

r ★★★★★
()
Ответ на: комментарий от r

Да, с зубами у тебя все порядке :)

> Про рейс кондишен тут было замечено и обсуждено.

Где? Или ты имееш в виду робкое замечание про семафоры и локи. Кстати, какое отношение имеют семафоры к средам?

> А еще у него плохо с системным мышлением - он готовит данные в предидущем процессе для неизвестного следующего.

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

> А то как ты попытался продемонстрировать этот рейс кондишен ты лучше сорти и никому не показывай.

Так ето же твой код. Ну ладно, 'писателя мануала по тредам' :) Я просто добавил цикл задержки после старта среды, чтобы выявить рейс кондишен. Хотя на машине с более чем двумя процессорами его и так бы было видно.

anonymous
()
Ответ на: комментарий от r

> Про рейс кондишен тут было замечено и обсуждено.

Ааа, нашел: sv75 * (*) (15.12.2007 0:43:40) Sorry, беру свои слова обратно.

Кстати, добавление sleep() race condition скорее всего не выявит, потому что sleep() ето точка прерывания, и в данном примере не нарушит порядок шедулинга сред

anonymous
()
Ответ на: комментарий от anonymous

>Кстати, добавление sleep() race condition скорее всего не выявит, потому что sleep() ето точка прерывания, и в данном примере не нарушит порядок шедулинга сред

Выявит:) Особенно если его поставить между принтами:) Так замечательно все треды за номером 1 оказываются:))))

r ★★★★★
()

По ходу понадобилось в Питоне убивать потоки снаружи, что-то вроде метода kill. Нашел два решения в виде костылей, оба работают только по границе вызова. Знает ли кто-нибудь нормальные решения?

eugine_kosenko ★★★
()
Ответ на: комментарий от AVL2

> >а расскажите почему __init__ нужно избегать я, например, не знаю, может еще кто не знает, было бы интересно.

> +1 > Ждем комментария ;)

Я не говорил, что *нужно* избегать. Я говорил что лучше (бы). Причины: называется в питоне он убого (да, я не нужно объяснять, почему он так называется), и конструктор родителя вызывается стремно.

В тяжелые моменты у меня есть ощущение, что лучше property и try в геттере для присваивания начального значения.

sv75 ★★★★★
()
Ответ на: комментарий от sv75

(к предыдуoему ответу). Есть примерно такая мысль про конструкторы (это велосипед?):

import copy

def initter(self, **args):
    for name in args.keys():
        self.__dict__[name] = args[name]

def getter(self, name):
    try:
        return self.__dict__[name]
    except:
        def_value = self.__class__.__dict__['_' + name]
        result =  eval(def_value)
        self.__dict__[name] = result
        return result

class A(object):
    _f1 = '[]'
    _f2 = 'A(f1=copy.copy(self.f1))'
    __getattr__ =getter
    __init__ = initter

a = A()
a.f1 += [1, 2]
a.f2.f1 += [3]
print 'a.f1:', a.f1
print 'a.f2.f1:', a.f2.f1

sv75 ★★★★★
()
Ответ на: комментарий от tailgunner

> Три года расстрела с последующим запретом на преподавание ^W^W^W^W^W^W^W^W лучше уж __init__

Чем лучше? :) А по-моему прикольненько, жаль немного непрозрачно. Зато ленивые вычисления ;)

sv75 ★★★★★
()
Ответ на: комментарий от tailgunner

Eval можно конечно и выкинуть, тогда вполне прозрачно, но вот возможностей поменьше :)

sv75 ★★★★★
()
Ответ на: комментарий от tailgunner

> Три года расстрела с последующим запретом на преподавание ^W^W^W^W^W^W^W^W лучше уж __init__

Давно я так не смеялся... :)

sv75 ★★★★★
()
Ответ на: комментарий от sv75

> Чем лучше? :)

Кода в разы меньше, и он на порядок проще.

> А по-моему прикольненько

Это да. Особенно прикалывает код внутри строкового литерала

> Зато ленивые вычисления ;)

...в виде eval o_O

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

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

Объявляем тендер на создание лучшего языка всех времен и народов. Основные требования:
- быстрое вычисление быдло-кодеров, кем бы они не притворялись;
- отключенная как класс многопоточность и замена на что-то адекватно-иное;
- стэклесс;
- только не ruby;
- и не ассемблер;
- и не хаскел;
- вообщем, _новый_ язык, а не велосипед;
- штобы был сразу с уникодой и для компенсации убогих - поддерживал разные кодировки;
- скриптовый - компилятор напишут те, кому это надо;
- встроенный xml и json парсер - желательно через единый класс;
- чтобы был достаточно шустрым (ориентация на скорость perl или python для типовых задач);
- защищенность от пользователя, такая, чтобы его в ядро можно было бы встроить без боязни deadlock или coredump;
- достаточно удобный и понятный код (ориентироваться на python, но не копировать полностью);
- втроенные средства СУБД (ориентация на Оракл, как на язык программирования, а не только как СУБД);
- шобы сотрудники microsoft кусали локти о невозможности патентования BSD кода этого языка.

anonymous
()
Ответ на: комментарий от anonymous

Это просто: берешь статически типизируемое подмножество Питон (RPython) привинчиваешь к нему каналы в стиле Occam (через EasyExtend, например) - и ты в деле.

8)

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

ммм. Скрестив ужа с ежом только гипотетически должна получится трех-метровая колючая проволока. Генетически же результатов может быть очень много - от плешивого ежа без ног, до продоговатого "зубастика". Фраза "это просто" тут не подходит.

anonymous
()
Ответ на: комментарий от anonymous

> Скрестив ужа с ежом только гипотетически должна получится трех-метровая колючая проволока

Ну так никто и не обещает, что с первого раза получится 8)

> Фраза "это просто" тут не подходит.

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

Так что в "сухом остатке" - эксперименты на базе Питона, с использованием EasyExtend и/или PyPy. Это вполне возможно технически.

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

> Вообще-то предложение было только отчасти серьезным.

Это да :) Просто хотел узнать как много человек задумываются о том же.

> Вещи типа "быстрого вычисления быдлокодеров" - недостижимы,

Согласен. Тем не менее структура python располагает делать отступы - большой плюс в борьбе с быдлокодерами. Минус - именовать переменные пока возможно только в ansii. Поэтому люди, которые не знают английского, оставлены один на один со своим маразмом.. что дает совершенно определенные результаты.

Это не единственное направление для развития.

> "_новый_ язык" банально не нужен,

"не нужен" - может быть, как и быть может и "никому не помешает".

> а "невозможность дэдлоков" вряд ли реализуема на практике.

при текущей организации мультипоточности от деадлоков никуда не деться. Но никто не запрещает создать другую схему работы по согласованной работе нескольких потоков. Вариантов масса. Не все они идеальны, вернее - практически ни один из них сам по себе не претендует на панацею при решении данной проблемы. Если посмотреть со стороны POSIX THREADS, тут также будет масса интерфейсов:
- pthread_mutex_*
- pthread_cond_*
- pthread_rwlock_*
..

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

anonymous
()
Ответ на: комментарий от tailgunner

> Так что в "сухом остатке" - эксперименты на базе Питона, с использованием EasyExtend и/или PyPy. Это вполне возможно технически.

Для создание прототипа языка ? Имеет смысл.

anonymous
()
Ответ на: комментарий от tailgunner

> Кода в разы меньше, и он на порядок проще.

После наследования останется писать только

class A(SuperInitterClass):

    _f1 = []
    _f2 = B() # eval выкинули по просьбе слабонервных

> Особенно прикалывает код внутри строкового литерала

А что собсно смущает? :)

> в качестве примера "как надо делать"

В качестве такого примера - не предлагается.

sv75 ★★★★★
()
Ответ на: комментарий от defmacro

> Чем так ужасен __init__? `__' коробят или что?

Ключевой вопрос: а для чего вы его используете? :)

sv75 ★★★★★
()
Ответ на: комментарий от defmacro

> Чем так ужасен __init__? `__' коробят или что?

Ключевой вопрос: а для чего вы его используете? :)

sv75 ★★★★★
()
Ответ на: комментарий от tailgunner

> ...в виде eval o_O

С eval короче выходит. Без eval:

class A(SuperObject):

    _f1 = []
    _f2 = lambda self: A(f1=copy(self.f1)) # длинновато!

sv75 ★★★★★
()
Ответ на: комментарий от sv75

> После наследования останется писать только

В чем цель-то? Любыми средствами избежать написания def __init__(self)? И для этого - городить 2 лишних функции с неочевидным поведением, и лишний класс? Сколько классов надо определить, чтобы получить выигрыш? Как initter и getter взаимодействуют со __slots__?

>> в качестве примера "как надо делать"

> В качестве такого примера - не предлагается.

Слава ТНБ.

> _f2 = lambda self: A(f1=copy(self.f1)) # длинновато!

Зато при синтаксической ошибке будет выдано нормальное сообщение при трансляции, а не исключение в рантайме.

tailgunner ★★★★★
()
Ответ на: комментарий от KRoN73

Это как "зеленые треды" в яве. С соответствующим ручным контролем за процессом.

AlexM ★★★★★
()
Ответ на: комментарий от AVL2

> Чем это вам конструкторы не угодили?

Это не конструктор. Это инициализатор. Равно как и __del__ - не деструктор.

AlexM ★★★★★
()
Ответ на: комментарий от tailgunner

> В чем цель-то? Любыми средствами избежать написания def __init__(self)?

Если бы только! Как описывать связь полей и тегов XML, к примеру?

> И для этого - городить 2 лишних функции с неочевидным поведением, и лишний класс? Сколько классов надо определить, чтобы получить выигрыш? Как initter и getter взаимодействуют со __slots__?

Если __slots__, то вместо геттера лучше автоматом создавать все поля объекта в иниттере.

> _f2 = lambda self: A(f1=copy(self.f1)) # длинновато!

Зато при синтаксической ошибке будет выдано нормальное сообщение при трансляции, а не исключение в рантайме.

Ага, особенно если ошибка в имени переменной, да.

sv75 ★★★★★
()
Ответ на: комментарий от sv75

>> В чем цель-то? Любыми средствами избежать написания def __init__(self)?

> Если бы только! Как описывать связь полей и тегов XML, к примеру?

Не понял. Чем для этого не подходят атрибуты класса?

>>> _f2 = lambda self: A(f1=copy(self.f1)) # длинновато!

>> Зато при синтаксической ошибке будет выдано нормальное сообщение при трансляции, а не исключение в рантайме.

> Ага, особенно если ошибка в имени переменной, да.

Это не является синтаксической ошибкой.

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

> Не понял. Чем для этого не подходят атрибуты класса?

Так я и использую атрибуты класса, нет? :) Причем значения по умолчанию и связь с хранилищем хотелось бы описывать рядом.

sv75 ★★★★★
()
Ответ на: комментарий от sv75

>> Не понял. Чем для этого не подходят атрибуты класса?

> Так я и использую атрибуты класса, нет? :)

Да, но ты их используешь (я так и не понял, зачем) через ж^H непонятно зачем нужные функции, вместо того, чтобы присвоить значения в __init__

> Причем значения по умолчанию и связь с хранилищем хотелось бы описывать рядом.

Это разумно, но зачем нужны initter и getter - я не понимаю (ну, кроме "прикольненько" :)).

tailgunner ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.