Найти - Пользователи
Полная версия: Объект в потоке
Начало » Python для новичков » Объект в потоке
1 2 3
nerijus
А если очень хочется прозрачности, то в данном случае луче это делать при помощи декораторов (засовывать в Queue для обработки).
Kogrom
Ed
Кстати, по-моему для вызова только __getattr__ переопределить достаточно. Зачем еще __setattr__ и __delattr__ переопределяются непонятно.
У меня тоже такой вопрос возник. На него автор ответил: “чтобы работало a = obj.blah; obj.blah = a; del obj.blah”.

Ed
Атрибуты с двумя подчеркиваниями рекомендуется использовать для атрибутов, которые хочется скрыть от доступа классов-наследников . Для обычных не публичных атрибутов используется одно подчеркивание слева.
Не совсем верно. Тут нам надо отделить атрибуты класса-обёртки от атрибутов обёртываемого класса. У последнего могут быть одноименные не публичные методы. Поэтому приватные методы.
Ed
Не нравится - это слишком легко сказано. Таким подходом закрываются любые ошибки в таким образом вызываемых функциях. Попробуйте в вашей функции написать какую-нибудь чушь, скажем bla-bla-bla и запустить. Разницы не заметите, хотя она банально не будет работать. И как такое отлаживать?
Но если не ловить исключение, то можно поток поломать. То есть, насколько я понимаю, программа может не завершиться. Поэтому я просто вместо pass у себя сделал вывод об ошибке в stderr.

Ну и имена исключений я неправильно определил.

nerijus
Вы уж меня простите но запускать каждый метод в новом потоке это просто кошмар.
У меня действительно маленький опыт работы с потоками в Python. Но я тут вижу только один поток, который обрабатывает очередь запросов. Где же тут каждый метод в отдельном потоке?
Kogrom
nerijus
Для решения таких задач, нужно создать thread pool и запихивать туда задачи (функции). А то что ты здесь пытаешься намудрить, очень похоже на отсутствие понятия что такое thread вообще. Вот посмотри пример: http://code.activestate.com/recipes/577187-python-thread-pool/ и перестань морочить себе голову со всякими враперами.
Кстати, чем-то похоже. И тоже ловят все исключения (если я правильно понял). Но выводят зачем-то в stdout.
nerijus
Kogrom
Но я тут вижу только один поток, который обрабатывает очередь запросов. Где же тут каждый метод в отдельном потоке?
a = ThreadProxy(TestClass())
b = ThreadProxy(TestClass())

Извини, не каждый метод, а каждый объект. Но все равно так делать не надо. Это во первых. Во вторых как я уже говорил, для того что бы запустить метод в отдельном потоке, засунь его в Queue и пусть этим занимаются потоки никак не связанные с объектами. Если хочешь меньше спагетти, можешь прикрыть методы декоратором.

Kogrom
Кстати, чем-то похоже. И тоже ловят все исключения (если я правильно понял). Но выводят зачем-то в stdout.
Ну там простой пример. Обработку исключений можно поменять, только нужно помнить что например запись в файл должна быть thread-safe (и вообще исключения ловить в стиле “try except Exception, e” плохо).
Ed
Kogrom
У меня тоже такой вопрос возник. На него автор ответил: “чтобы работало a = obj.blah; obj.blah = a; del obj.blah”.
Я в курсе для чего переопределяют setattr и delattr, но не вижу применения им в данной задаче. Повторюсь, для вызова методов достаточно переопределить getattr. Кроме вызова методов я ничего в вашем коде не вижу. А иметь лишний код для того чтобы он просто был не считаю разумным.

Kogrom
Не совсем верно. Тут нам надо отделить атрибуты класса-обёртки от атрибутов обёртываемого класса. У последнего могут быть одноименные не публичные методы. Поэтому приватные методы
Хех :( Ну давайте смотреть код тогда. Похоже теоретически вас не переубедить.
Покажите мне, скажем, необходимость двух подчеркиваний перед вашим self.__requests, __obj, __worker.
Это не методы, вызываться через ваш прокси они не будут, даже если таковые и будут в ваших обертываемых классах.
Теперь о методах. Возьмем __run. Вы серьезно думаете, что вызов приватного _run из обертываемого класса - это хороший дизайн? По-моему таким образом кроме публичных методов ничего не должно вызываться.
.
Но если не ловить исключение, то можно поток поломать. То есть, насколько я понимаю, программа может не завершиться. Поэтому я просто вместо pass у себя сделал вывод об ошибке в stderr.
Я и не предлагал не ловить исключение. Я возражал против тупого игнорирования всех исключений.
Kogrom
nerijus
a = ThreadProxy(TestClass())
b = ThreadProxy(TestClass())

Извини, не каждый метод, а каждый объект. Но все равно так делать не надо.
“Так делать не надо” - слишком неопределенный совет. Вероятно, подразумевался совет: не следует запускать слишком много потоков. У меня такой объект в потоке один на всю программу, так что этот совет я учитываю.

nerijus
Если хочешь меньше спагетти, можешь прикрыть методы декоратором.
Ну, а это у меня что? Декоратор в чистом виде, если говорим о паттернах GoF.
Ed
Kogrom
У меня действительно маленький опыт работы с потоками в Python. Но я тут вижу только один поток, который обрабатывает очередь запросов. Где же тут каждый метод в отдельном потоке?
Кстати, все треды будут работать на одном core. Если это не то, чего хотелось, то можно попользоваться multiprocessing.

Ну и да, ваша метода неприменима для более-менее долгих задач. Они будут тормозить очередь.

И еще одно - никак не обрабатываются возвращаемые значения вызываемых методов. То есть если кроме побочных эффектов интересует еще и результат, то вы его при таком подходе теряете. С побочными эффектами тоже не все хорошо. С ними нужно где-то в коде синхронизироваться, то есть подход не обеспечивает нужной прозрачности.
Kogrom
Ed
Я в курсе для чего переопределяют setattr и delattr, но не вижу применения им в данной задаче.
В какой данной задаче? То, что запускается, когда модуль является главным - это не задача, а тест работы. Причём не полный. Он нужен для того, чтобы человек, использующий использующий этот класс (точнее, модуль) мог быстрее понять о его предназначении.

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

Ed
ХПокажите мне, скажем, необходимость двух подчеркиваний перед вашим self.__requests, __obj, __worker.
Это не методы, вызываться через ваш прокси они не будут, даже если таковые и будут в ваших обертываемых классах.
Они вызываются:
attr = getattr(self.__obj, key)
if not callable(attr): return attr
Ed
Теперь о методах. Возьмем __run. Вы серьезно думаете, что вызов приватного _run из обертываемого класса - это хороший дизайн? По-моему таким образом кроме публичных методов ничего не должно вызываться.
Ок. Почему методы с одним подчеркиванием вообще доступны? Гвидо ван Россум хотел сделать приятное быдлокодерам?

Ed
Я и не предлагал не ловить исключение. Я возражал против тупого игнорирования всех исключений.
Ну хоть в чём-то договорились :)
Kogrom
Ed
Кстати, все треды будут работать на одном core. Если это не то, чего хотелось, то можно попользоваться multiprocessing.
Я в курсе. Но меня это пока устраивает.

Ed
И еще одно - никак не обрабатываются возвращаемые значения вызываемых методов. То есть если кроме побочных эффектов интересует еще и результат, то вы его при таком подходе теряете.
Похоже, что так. И с ходу я не вижу элегантного решения этой проблемы, ибо запускающая функция не должна дожидаться ответа. Можно передавать объект среди параметров, который будет получать результат. Я пока делаю так. Но это не очень красиво.
Ed
Kogrom
В какой данной задаче? То, что запускается, когда модуль является главным - это не задача, а тест работы. Причём не полный. Он нужен для того, чтобы человек, использующий использующий этот класс (точнее, модуль) мог быстрее понять о его предназначении.
Чудесно. покажите как вы собираетесь использовать __setattr__ и __delattr__ для вашего класса. Я просто подумал, что цель - это вызвать метод объекта. Если вы собираетесь еще и назначать его атрибуты извне через этот прокси, то мой вопрос отпал как дурацкий. Да и вообще на основании чего мне делать выводы. Вы нигде не указали, что это неполный тест :)

Они вызываются:
attr = getattr(self.__obj, key)
if not callable(attr): return attr
Это вопрос реализации приоритетов. Можно сначала проверять атрибуты прокси, а потом уже проксируемого объекта и этой проблемы не будет.

Вы вот спорите, а скорее всего так и не почитали PEP8. Он писан людьми гораздо умнее нас с вами и на основании их опыта. Я склонен больше доверять им, чем вам, извините. Если они пишут, что использовать одно подчеркивание для непубличных методов лучше, значит лучше.

Ок. Почему методы с одним подчеркиванием вообще доступны? Гвидо ван Россум хотел сделать приятное быдлокодерам?
Он хотел сделать язык нежестким и у него получилось. В смысле того, что отвественность лежит на программисте в конечном счете. Если кто-то хочет доступаться извне к внутренним переменным - это его решение. Незачем устраивать террор там, где он не нужен.

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

Ну хоть в чём-то договорились :)
На самом деле мы уже о многом договорились, просто вы в пылу спора не замечаете :)
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB