There may be a better way, but the following one will work, which directly looks up module’s __dict__:
import torch.nn as nn


class Foo(nn.Module):
    def __init__(self):
        super().__init__()
        self.conv = nn.Conv2d(1, 2, 3)

foo = Foo()

def hook(m, i, o):
    print(m, i, o)

def pre_hook(m, i):
    print(m, i)

foo.register_forward_hook(hook)
foo.conv.register_forward_hook(hook)
foo.register_forward_pre_hook(pre_hook)

save = []
def find_hook(m):
    module_name = type(m).__name__
    for k, v in m._forward_hooks.items():
        save.append((module_name, k, v.__name__))
        
    for k, v in m._forward_pre_hooks.items():
        save.append((module_name, k, v.__name__))
        
    for k, v in m._backward_hooks.items():
        save.append((module_name, k, v.__name__))

foo.apply(find_hook)
print(save)

which prints out
[('Conv2d', 1, 'hook'), ('Foo', 0, 'hook'), ('Foo', 2, 'pre_hook')]