python模块变量如何工作?

时间:2010-08-24 17:03:26

标签: python import module

我曾经认为,一旦加载了模块,如果其他文件导入了相同的模块,或者以不同的方式导入模块,则不会重新导入。例如,我的mdir/__init__.py为空,mdir/mymod.py为:

thenum = None
def setNum(n):
    global thenum
    if thenum is not None:
        raise ValueError("Num already set")
    thenum = n

def getNum():
    if thenum is None:
        raise ValueError("Num hasn't been set")
    return thenum

来自同一文件的前几个用例根据期望进行。此文件为./usage.py,文件夹mdir位于:

import mdir.mymod

mdir.mymod.setNum(4)
print mdir.mymod.getNum()

from mdir import mymod
print mymod.getNum()

from mdir.mymod import *
print getNum()
try:
    setNum(10)
except ValueError:
    print "YHep, exception"

输出符合预期:

4
4
4
YHep, exception

但是,如果我弄乱系统路径,那么看起来模块会重新导入:

#BEHOLD
import sys
sys.path.append("mdir")
import mymod
try:
    mymod.getNum()
except ValueError:
    print "Should not have gotten exception"

mymod.setNum(10)
print mymod.getNum()
print mdir.mymod.getNum()

该代码在前一代码之后运行,产生:

Should not have gotten exception
10
4

是什么给出了?

1 个答案:

答案 0 :(得分:4)

mymodmdir.mymod被视为不同的模块 - 这里有一些相关的讨论:http://code.djangoproject.com/ticket/3951

<强>解释

最好与python交互式解释器一起玩,亲眼看看。我在某个目录下创建了目录(包)mydir,在其中创建了两个文件(模块) - __init__.pymymod.py,两者都是空的。我在包含mydir的目录中启动了python。现在看看会发生什么:

>>> import mydir.mymod
>>> from mydir import mymod
>>> mymod == mydir.mymod
True

为什么mymodmydir.mymod被视为同一件事?好吧,两个名称都引用相同的模块对象 - 模块的相等性由它们的路径比较决定:

>>> mymod
<module 'mydir.mymod' from 'mydir\mymod.py'>
>>> mydir.mymod
<module 'mydir.mymod' from 'mydir\mymod.py'>

现在,如果我改变sys.path以包含mydir并导入mymod,导入模块的路径似乎会有所不同:< / p>

>>> import sys
>>> sys.path.append( "d:/zrodla/stack/mydir" )
# note that importing mymod (and not mydir.mymod) prior to appending mydir to 
# path would cause an error
>>> mymod2
<module 'mymod' from 'd:/zrodla/stack/mydir\mymod.pyc'>
>>> mymod2 == mydir.mymod
False

然后生成的模块对象将不会比较相等。这样一个模块将被导入两次 - 这是正常的,这就是python的工作方式。请记住,导入的模块由其路径标识 - 更具体地说,我想是'虚线路径' - 查看sys.modules键:

>>> [x for x in sys.modules.keys() if "my" in x]
['mydir', 'mymod', 'mydir.mymod']

我希望现在很清楚。