Как работают переменные модуля Python? - PullRequest
2 голосов
/ 24 августа 2010

Раньше я думал, что после загрузки модуля повторный импорт не будет выполняться, если другие файлы импортировали тот же модуль или если он был импортирован другими способами. Например, у меня есть 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 Ответ

4 голосов
/ 24 августа 2010

mymod и mdir.mymod считаются разными модулями - вот несколько взаимосвязанное обсуждение: http://code.djangoproject.com/ticket/3951

Объяснение:

Лучше всего играть с Python Interactiveпереводчик и убедитесь сами.Я создал каталог (пакет) mydir в некотором каталоге и внутри него два файла (модуля) - __init__.py и mymod.py, оба пустые.Я запустил python внутри директории, содержащей mydir.Теперь посмотрим, что происходит:

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

Почему mymod и mydir.mymod считаются одним и тем же?Итак, оба имени относятся к одному и тому же объекту модуля - равенство модулей определяется сравнением их путей:

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

Теперь, если я изменю sys.path на mydir и импортируюmymod таким образом, что путь импортируемого модуля будет казаться другим:

>>> 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']

Надеюсь, теперь все ясно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...