Pythonでモジュールをアンインポートする方法

モジュールをインポートするときの問題点

Pythonで同名の別ファイルをインポートしようとすると、あとにインポートしたファイルがきちんとインポートされません。
なぜなら、 Python側がすでにインポートしているファイルだと勘違いしてしまうからです。
この問題を解決するために、先にインポートしているモジュールをアンインポートして、別の場所にある同名ファイルをインポートできるようにしましょう。

問題の検証

ここからは、問題の検証をしようと思うので、結論を急ぐ方は「アンインポートの解決策」を見てください。

まず例えば、以下のような2種類のスクリプトを用意しましょう。

以下のスクリプトは「Test.py」というタイトルのファイル。
このファイルは「A」というフォルダと、「B」というフォルダの2つに入れておきましょう。
ちなみに、Python 3.x系を使っているので、2.x系を使っている人は、print文の括弧を外すと動くはずです。

#!/usr/bin/env python
# -*- coding: utf-8 -*-

def print_path():
    print(__file__)

以下のスクリプトは「Load.py」という名前のファイル。
「./A/Test.py」を読み込んで、print_path関数を実行し、「./B /Test.py」を読み込んで、print_path関数を実行します。

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import sys

sys.path.append('./A')
import Test
Test.print_path()
sys.path.remove('./A')

sys.path.append('./B')
import Test
Test.print_path()
sys.path.remove('./B')

「sys.path」にモジュールのあるディレクトリを加えたあとに、「import」することで必要なファイルを使うことができます。

このファイルを実行すると、以下のように出力されます。

./A/Test.py
./A/Test.py

両方とも「./A/Test.py」であることから、「./B/Test.py」が呼ばれていないことがわかります。
このような状況ですと、いったん「./A/Test.py」をアンインポートしたほうが良さそうですね。

しかしながら、Pythonにはモジュールをインポートする「import」はあっても、アンインポートする「unimport」は見当たらないようです。

アンインポートの解決策

自分もちょっと悩んだのですが、実はモジュール情報を記憶している箇所を少し触ることで、モジュールのアンインポート機能が実装できるようです。

以下のスクリプトがアンインポート機能の実装です。

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import sys

sys.path.append('./A')
import Test
Test.print_path()
sys.modules.pop('Test') # Unimport module forcely
sys.path.remove('./A')

sys.path.append('./B')
import Test
Test.print_path()
sys.modules.pop('Test') # Unimport module forcely
sys.path.remove('./B')

インポートしたモジュールは「sys.modules」に格納されているため、そこから該当の要素を取り除くことで、アンインポートできるようです。

これを実行すると、以下のような結果になります。

./A/Test.py
./B/Test.py

無事にアンインポートできているようです。
ちょっと強引な処理ですが、必要なときはこれで乗り切りましょう。