Как показано в трассировке (что вы должны были опубликовать FWIW), ваша ошибка не в вызове SomeFn()
, а в доступе к beam.DoFn
в классе SomeFn
определение. И причина вполне очевидна: вы очень явно указали Python сделать это простым переопределением Beam.__getattribute__
.
Обратите внимание, что object.__getattribute__
является официальной реализацией поиска атрибутов по умолчанию (она вызывается каждый раз, когда Python видит либо obj.name
, либо getattr (obj, "name"), и что этот метод лучше оставьте в покое, если вы не полностью понимаете последствия его отмены И не можете найти лучшего решения.
В этом случае очень очевидное решение - вместо этого реализовать __getattr__
, который вызывается только __getattribute__
в качестве последнего средства если атрибут не может быть разрешен каким-либо другим способом. Вы говорите, что:
Также заменить getattribute на getattr не работал
, но я только что попробовал его на вашем фрагмент кода и он (конечно) дает ожидаемый результат. Является ли это тем, чего ожидал , которого вы ожидали, это другой вопрос, но, поскольку вы ни опубликовали эту версию своего кода, ни пытались объяснить, как он "не работал ", вы не можете ожидать никакого ответа по этому вопросу (подсказка:" не работает "- это абсолютно бесполезное описание проблемы).
Как последнее замечание:
он успешно загрузит все методы луча, такие как DoFn и конвейер ... В приведенном выше коде сейчас вызывается луч. DoFn
Кажется, вы немного запутался в терминологии. DoFn
и Pipeline
являются классами, а не методами, и (как уже упоминалось) ваша ошибка возникает, когда обращается к beam.DoFn
, а не когда вызывает .
РЕДАКТИРОВАТЬ:
by не работал Я имел в виду, что это не дает мне ошибку, когда я пытаюсь получить доступ к beam.DoFn или SomeFn () при использовании Вместо этого getattr getattribute (...) я хочу вызвать ошибку при вызове someFn без доступа к лучу. DoFn
Хорошо, похоже, вы не совсем получили порядок выполнения вызова метода выражение. Когда вы делаете
obj.method()
, это фактически сокращение для
method = obj.__getattribute__("method")
method.__call__()
Так что переопределение __getattribute__
не является правильным решением (см. Выше), а определение __getattr__
бесполезно здесь - ваши атрибуты DummyBeam
class HAS DoFn
и Pipeline
, поэтому __getattr__
просто не будут вызываться для этих имен.
Теперь причина, по которой вы не получаете никаких исключений при вызове beam.DoFn
или beam.Pipeline
означает, что эти имена связаны с вашим Empty
классом , а не с экземплярами этого класса, поэтому вы на самом деле никогда не вызываете Empty.__call__
. Метод Rhe __call__
, определенный в классе, используется только тогда, когда вызывается экземпляр этого класса, а не при создании экземпляра класса (в этом случае вызывается метод __call__
метакласса):
>>> class MyCallable:
... def __init__(self):
... print("in MyCallable.__init__")
... def __call__(self):
... print("in MyCallable.__call__")
...
>>>
... c = MyCallable()
in MyCallable.__init__
>>> c()
in MyCallable.__call__
>>>
Так что, если вы хотите поднять свое исключение, когда кто-то пытается создать DoFn
или ̀Pipeline you either have to make them instances of
Empty or keep them as they are and rename
Empty. call to
Пусто. new which is the first method called by
type. call (
type` - метакласс по умолчанию для всех классов).