Python 3 中未为信号处理程序调用 MagicMock

MagicMock not called for signal handler in Python 3

我正在将一些代码和相关测试从 python 2 迁移到 python 3(特别是 2.7 到 3.7),我遇到了我想要的这种奇怪的行为了解:

try:
    from unittest import mock  # python 3
except ImportError:
    import mock  # python 2
import os
import signal


def do_signal(mock_type):
    def side_effect(signum, frame):
        print('Called for ' + mock_type.__name__)
    handler = mock_type(side_effect=side_effect)
    signal.signal(signal.SIGTERM, handler)
    os.kill(os.getpid(), signal.SIGTERM)
    print(handler.call_count)


do_signal(mock.Mock)
do_signal(mock.MagicMock)

这里我使用了一个mock.Mockmock.MagicMock作为信号处理程序,并且在向当前进程发送信号后打印出mock被调用的次数。

在 python 2.7 中打印出:

Called for Mock
1
Called for MagicMock
1

但是对于 python3.7,它打印出:

Called for Mock
1
0

对于 python 3,似乎根本没有调用 MagicMock。颠倒 do_signal 调用的顺序不会改变这一点。

MockMagicMock 之间的哪些行为差异可以解释这一点,为什么行为会从 python 2 变为 3?我知道 mock 在 python 3 中作为 unittest.mock 添加到标准库中,所以我很好奇那里是否发生了某些变化。

在python 3中,为信号添加了枚举

例如,您可以调用:

signal.signal(signal.SIGINT, signal.SIG_IGN)

signal.signal 尝试做的第一件事是通过调用 int(...)

将句柄从枚举转换为整数

因为MagicMock支持所有的魔法方法,它也支持__int__

如果你偷看神奇的方法调用,你可以看到这一点:

    # ...
    try:
        print(handler.__int__.call_count)
    except AttributeError:
        print('__int__ not called')

因为 MagicMock 有 __int__ :

>>> mock.MagicMock().__int__()
1

SIGTERM 处理程序重新分配给信号 1(SIGHUP 在我的平台上)