Обернутые функции модуля Python вызывают ошибку TypeErrorPython

Программы на Python
Ответить Пред. темаСлед. тема
Anonymous
 Обернутые функции модуля Python вызывают ошибку TypeError

Сообщение Anonymous »

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

Код: Выделить всё

def wrap_module_with_warnings(module):
for fn_name, fn in inspect.getmembers(module):
if (not (inspect.isfunction(fn) or inspect.ismethod(fn))
or fn_name.startswith('_')
or inspect.getmodule(fn) is not module):
continue

@functools.wraps(fn)
def wrapped_fn(*args, **kwargs):
warnings.warn(f"The function {fn_name} was called.")
return fn(*args, **kwargs)

setattr(module, fn_name, wrapped_fn)
К сожалению, эта функция работает не так, как я ожидал. Я ожидаю, что он заменит все функции в модуле его обернутым вариантом, который просто выводит предупреждение, а затем вызывает исходную функцию. Однако на самом деле он выдает TypeError: объект «модуль» не может быть вызван:

Код: Выделить всё

/tmp/question/main.py:22: UserWarning: The function random was called.
warnings.warn(f"The function {fn_name} was called.")
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
File /tmp/question/main.py:31
29 print(f"Output before wrapping: {mod.f()}")
30 wrap_module_with_warnings(mod)
---> 31 print(f"Output after wrapping: {mod.f()}")

File /tmp/question/main.py:23, in wrap_module_with_warnings..wrapped_fn(*args, **kwargs)
20 @functools.wraps(fn)
21 def wrapped_fn(*args, **kwargs):
22     warnings.warn(f"The function {fn_name} was called.")
---> 23     return fn(*args, **kwargs)

TypeError: 'module' object is not callable
Чтобы продемонстрировать свою проблему, я использую следующий основной код:

Код: Выделить всё

import mod

if __name__ == '__main__':
print(f"Output before wrapping: {mod.f()}")
wrap_module_with_warnings(mod)
print(f"Output after wrapping: {mod.f()}")
и пример модуля mod.py:

Код: Выделить всё

import random

def f() -> int:
return random.randint(0, 1000)
Ошибка предполагает, что mod.f является модулем. Проверка типа mod.f после вызова моего метода-оболочки показывает, что на самом деле это функция:

Код: Выделить всё

In [1]: type(mod.f)
Out[1]: function
Чтобы изучить исходную функцию, я изменил последнюю строку файла capture_module_with_warnings на:

Код: Выделить всё

setattr(module, fn_name, (fn, wrapped_fn))
и проверить mod.f после вызова оболочки тоже не особо поможет:

Код: Выделить всё

In [1]: mod.f[0]
Out[1]:  int>

In [2]: mod.f[1]
Out[2]:  int>

In [3]: type(mod.f[0])
Out[3]: function

In [4]: type(mod.f[1])
Out[4]: function

In [5]: mod.f[0]()
Out[5]: 785

In [6]: mod.f[1]()
/tmp/AscendSpeed/q/main.py:22: UserWarning: The function random was called.
warnings.warn(f"The function {fn_name} was called.")
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
Cell In[6], line 1
----> 1 mod.f[1]()

File /tmp/AscendSpeed/q/main.py:23, in wrap_module_with_warnings..wrapped_fn(*args, **kwargs)
20 @functools.wraps(fn)
21 def wrapped_fn(*args, **kwargs):
22     warnings.warn(f"The function {fn_name} was called.")
---> 23     return fn(*args, **kwargs)

TypeError: 'module' object is not callable
Я почти уверен, что этот код должен работать, fn должна быть функцией mod.f, но зачем мне это делать? тогда получить TypeError?

Подробнее здесь: https://stackoverflow.com/questions/786 ... -typeerror
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение

Вернуться в «Python»