python3 標準関数に割り込み処理を入れたい


やりたい事はタイトルのままなのですが、具体的には

[code]

    @printの割り込み処理
    def interrupt():
        print('割り込み処理')
    
    # あるいは
    @割り込み処理
    def interrupt():
        if __割り込み元を持っているもの__ == print:
            print('割り込み処理')
    
    print('通常出力')
    
    # 出力
    割り込み処理
    通常出力
    
[/code]

みたいな事ができれば良いのですが、上記のような事は出来ますでしょうか？  
例ではprintとしていますが、printに限りません。  
なお、python3系です。

出来なければ出来ない、という回答がいただけると助かります。  
出来ない場合、どういう工夫でそれっぽい事が出来るのか、アイデアをもらえるとそれはそれ嬉しいです。

例えば

[code]

    INTERRUPT = True
    
    @ユーザー関数のprint
    def user_print(message, interrupt_flag=INTERRUPT)
        if interrupt_flag:
            interrupt()
        print(message)
    
[/code]

みたいな方法になるのかな、と漠然と考えています。




以下は`print`を自前の関数に置き換え、元の組込み`print`の実行前にメッセージを出す例です。

### [builtins](https://docs.python.org/ja/3/library/builtins.html)
経由での全体的な置き換え

[builtins](https://docs.python.org/ja/3/library/builtins.html)モジュール経由で組み込みオブジェクトの名前空間を参照して、自前の関数に置き換える方法です。  
この操作を行なうファイルだけでなく、他のモジュールにも影響します。

[code]

    #!/usr/bin/python3
    # 本物の組込みprint関数の値を保存しておく
    orig_print = print
    
    # 自前のprint用関数を定義する
    def my_print(*args):
        orig_print("# カスタム版printが呼ばれました")   # 追加したい処理
        return orig_print(*args)   # 元のprintの呼び出し
    
    # トップレベル（組込み識別子の名前空間）のprintを自前のものにする
    import builtins
    builtins.print = my_print
    
    # このファイルでprintという変数は定義されていないので、
    # ここでのprintはトップレベル（組込み識別子の名前空間）のprintとなる
    # そして、それは上で置き換え済み
    print("hello, world")
    
[/code]

出力:

[code]

    # カスタム版printが呼ばれました
    hello, world
    
[/code]

### 現在のファイル（モジュール）で`print`を定義

Pythonでは、最初の代入で現在のローカル名前空間内の変数が作られることを利用し、`print`変数に自前の関数を代入してしまいます。  
この場合、トップレベル（組込み識別子の名前空間）の`print`はそのままですから、他のモジュールでの`print`の呼び出しには影響しません。

[code]

    print = my_print   # my_print の定義は上を参照
    print("hello, world")
    
[/code]

### 特定のモジュールの名前空間に `print` を追加

下のように、モジュールに`print`を追加してしまえば、そのモジュール内で`print`が呼び出された際には、これが呼ばれることになります。

[code]

    import module_a
    module_a.print = my_print   # my_print の定義は上を参照
    
[/code]

### その他

テストやデバッグ目的としては、[`unittest.mock`](https://docs.python.org/ja/dev/library/unittest.mock.html)モジュールも参考になるかと思います。




以下は`print`を自前の関数に置き換え、元の組込み`print`の実行前にメッセージを出す例です。

### [builtins](https://docs.python.org/ja/3/library/builtins.html)
経由での全体的な置き換え

[builtins](https://docs.python.org/ja/3/library/builtins.html)モジュール経由で組み込みオブジェクトの名前空間を参照して、自前の関数に置き換える方法です。  
この操作を行なうファイルだけでなく、他のモジュールにも影響します。

[code]

    #!/usr/bin/python3
    # 本物の組込みprint関数の値を保存しておく
    orig_print = print
    
    # 自前のprint用関数を定義する
    def my_print(*args):
        orig_print("# カスタム版printが呼ばれました")   # 追加したい処理
        return orig_print(*args)   # 元のprintの呼び出し
    
    # トップレベル（組込み識別子の名前空間）のprintを自前のものにする
    import builtins
    builtins.print = my_print
    
    # このファイルでprintという変数は定義されていないので、
    # ここでのprintはトップレベル（組込み識別子の名前空間）のprintとなる
    # そして、それは上で置き換え済み
    print("hello, world")
    
[/code]

出力:

[code]

    # カスタム版printが呼ばれました
    hello, world
    
[/code]

### 現在のファイル（モジュール）で`print`を定義

Pythonでは、最初の代入で現在のローカル名前空間内の変数が作られることを利用し、`print`変数に自前の関数を代入してしまいます。  
この場合、トップレベル（組込み識別子の名前空間）の`print`はそのままですから、他のモジュールでの`print`の呼び出しには影響しません。

[code]

    print = my_print   # my_print の定義は上を参照
    print("hello, world")
    
[/code]

### 特定のモジュールの名前空間に `print` を追加

下のように、モジュールに`print`を追加してしまえば、そのモジュール内で`print`が呼び出された際には、これが呼ばれることになります。

[code]

    import module_a
    module_a.print = my_print   # my_print の定義は上を参照
    
[/code]

### その他

テストやデバッグ目的としては、[`unittest.mock`](https://docs.python.org/ja/dev/library/unittest.mock.html)モジュールも参考になるかと思います。

