メモ代わり。てきとーに。 いや、ですからてきとーですって。 2年前ぐらいにPythonあたりでメールくれた方、ごめんなさい。メール紛失してしまい無視した形になってしまいました。。。

2008年2月16日土曜日

[Python][お勉強] Python入門(37) - モジュールのリロード

続いてモジュールのリロードをやる。

モジュールのコードがメモリ上にロードされ、実行されるのは原則1プロセス1回。
どうしても再ロード、実行するにはreload関数を使う。
仮に2回同じモジュールをimportしてもロードされ実行されるのは初回のみ。

早速reload関数を使ってみる。

まずへぼモジュールを作成。


$ cat hebo.py
print "start loading"

X = 10
Y = 20

def aaa(x):
print "param is ", x
print "X = ", X
print "Y = ", Y


print "done"

 

こんな感じのプログラムがあったとする。
で、トップレベルからimport。

$ python
Python 2.4.4 (#2, Apr 5 2007, 20:11:18)
[GCC 4.1.2 20061115 (prerelease) (Debian 4.1.1-21)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import hebo
start loading
done
>>>
 

うむ。一回ロードされた。
一応もう一度importしてみる。

>>> import hebo
>>>
 

今度は実行されなかった。

で、pythonをCTRL-Zでバックグラウンドにし、heboモジュールを変更してみる。

$ cat hebo.py
print "start loading start start"

X = 10
Y = 20

def aaa(x):
print "param is ", x
print "X = ", X
print "Y = ", Y


print "done done done"
 

・・・ちょっとメッセージが変わっただけ。
で、これをもう一度import。

$ fg
python
import hebo
import hebo
>>>
 

なにも実行されない。
ここでreload関数を使ってみる。


>>> reload(hebo)
start loading start start
done done done
<module>
>>>
 

モジュールが実行された。ちゃんと書き換えたメッセージが実行された。
これじゃロードされたのか良くわからないので、さらにhebo.pyを書き換える。

$ cat hebo.py
print "start loading start start"

X = 10
Y = 20

def aaa(x):
print "param is BOYOYON ", x
print "X = ", X
print "Y = ", Y


print "done done done"
 

aaa関数の最初のメッセージを書き換えた。
で、pythonに戻り・・・

>>> hebo.aaa(10)
param is 10
X = 10
Y = 20
>>>
 

現状は書き換えた後リロードしていないので、以前のメッセージが表示されている。
で、リロード。

>>> reload(hebo)
start loading start start
done done done
<module>
 

さらにaaa関数を呼んでみる。

>>> hebo.aaa(10)
param is BOYOYON 10
X = 10
Y = 20
>>>
 

ぼよよんって言われた。
heboがリロードされてメモリ上にロードされているっぽいことが
確認できる。


リロードと変数、名前空間の関係
  1. リロードでは、モジュールの名前空間に変更が加えられる。
  2. リロード時に代入が行われると、変数の値は新しいものに置き換えられる。
  3. リロードを行うと、同じモジュールをimportステートメントでインポートしている全てのモジュールに影響を与える。
  4. fromステートメントによってモジュールをインポートした後にリロードが行われても影響を受けない。
とのこと。
1は、リロードが行われると、モジュールの名前空間をそのままに、必要に応じて変更が加えられるということ。いったんメモリ上の名前空間を全削除して再構成されるわけではない。

2は、リロードされるモジュールのトップレベルで代入が行われているのであれば、リロード後はリロード時に代入された値になる。
日本語じゃ、よくわからないのでやってみる。

>>> import hebo
start loading start start
done done done
>>> hebo.X
10
>>>
 

いま、hebo.Xの値は10。
これを上書きしてみる。

>>> hebo.X = 100000
>>> hebo.X
100000
>>>
 

上書きされた。
で、リロード。

>>> reload(hebo)
start loading start start
done done done
<module>
>>> hebo.X
10
>>>
 

リロードすると、hebo.Xの値は10になる。
なぜかというと、モジュールのトップレベルで代入されているから。
って感じか。

3は、リロードするとメモリ上のモジュールが変更されるので、他のimportで同じモジュールを参照しているモジュールにも影響を及ぼすということか。つまり他のモジュールも同じモジュールであれば同じメモリ領域を参照する、ということを言っているに違いない。


4はfromステートメントはコピーを作るのでリロードされても関係ないよ、といっている。


なるほどねー。



おしまい。

.

0 コメント: