модуль, повторно импортированный, если импортировано из другого пути

Созданный в сервере столь же не настраивается, и он работает на нечетном порте, поэтому если Ваше рассчитывание на определенное поведение это может быть неприятно.

8
задан CharlesB 25 February 2013 в 15:30
поделиться

2 ответа

Я могу воспроизвести это, только если main.py - это файл, который вы действительно запускаете. В этом случае вы получите текущий каталог main.py по пути sys. Но, очевидно, у вас также есть системный путь, установленный для импорта mypackage.

Python в этой ситуации не поймет, что mymodule и mypackage.mymodule - это один и тот же модуль, и вы получите этот эффект. Это изменение иллюстрирует это:

def add(x):
    from mypackage import mymodule
    print "mypackage.mymodule path", mymodule
    mymodule.l.append(x)
    print "updated list",mymodule.l

def get():
    import mymodule
    print "mymodule path", mymodule
    return mymodule.l

add(1)
print "lets check",get()

add(1)
print "lets check again",get()


$ export PYTHONPATH=.
$ python  mypackage/main.py 

mypackage.mymodule path <module 'mypackage.mymodule' from '/tmp/mypackage/mymodule.pyc'>
mymodule path <module 'mymodule' from '/tmp/mypackage/mymodule.pyc'>

Но добавьте еще один основной файл в текущий каталог:

realmain.py:
from mypackage import main

, и результат будет другим:

mypackage.mymodule path <module 'mypackage.mymodule' from '/tmp/mypackage/mymodule.pyc'>
mymodule path <module 'mypackage.mymodule' from '/tmp/mypackage/mymodule.pyc'>

Итак, я подозреваю, что ваш основной файл python находится внутри пакета. И в таком случае выход - не делать этого. : -)

3
ответ дан 5 December 2019 в 21:20
поделиться

Каждое пространство имен модуля импортируется только один раз. Проблема в том, что вы импортируете их по-другому. В первом вы выполняете импорт из глобального пакета, а во втором вы выполняете локальный, неупакованный импорт . Python считает модули разными. Первый импорт кэшируется во внутреннем кэше как mypackage.mymodule , а второй - только как mymodule .

Чтобы решить эту проблему, всегда используйте абсолютный импорт . То есть всегда указывайте модулю абсолютные пути импорта из пакета верхнего уровня и далее:

def add(x):
    from mypackage import mymodule
    mymodule.l.append(x)
    print "updated list",mymodule.l

def get():
    from mypackage import mymodule
    return mymodule.l

Помните, что ваша точка входа (файл, который вы запускаете, main.py ) также должна быть вне пакет. Если вы хотите, чтобы код точки входа находился внутри пакета, обычно вместо этого вы используете небольшой скрипт. Пример:

runme.py , вне пакета:

from mypackage.main import main
main()

И в main.py вы добавляете:

def main():
    # your code

Я считаю, что этот документ Дж. П. Кальдерона является отличный совет о том, как (не) структурировать свой проект Python. После этого у вас не будет проблем. Обратите внимание на папку bin - она ​​находится вне пакета. Я воспроизведу здесь весь текст:

Структура файловой системы проекта Python

Сделайте :

  • назовите каталог something связанные с вашим проектом. Например, если ваш проект называется " Twisted ", назовите каталог верхнего уровня для его исходные файлы Twisted . Когда ты делаешь релизы, вы должны включить версию суффикс номера: Twisted-2.5 .
  • создать каталог Twisted / bin и поместите туда свои исполняемые файлы, если вы есть какой-либо. Не давайте им .py расширение, даже если они Python исходные файлы. Не вставляйте код их, за исключением импорта и вызова основная функция определена где-то еще в ваших проектах.
  • Если ваш проект выражается как один Python исходный файл, затем поместите его в каталог и назовите его как-нибудь связанные с вашим проектом. Например, Twisted / twisted.py . Если тебе надо несколько исходных файлов, создайте пакет вместо этого ( Twisted / twisted / , с пустым Twisted / twisted / __ init __. Py ) и поместите в него свои исходные файлы. За пример, Скрученный / скрученный / internet.py .
  • положить ваши модульные тесты в подпакете ваш пакет (примечание - это означает, что вариант с одним исходным файлом Python выше был трюк - вам всегда нужно на хотя бы еще один файл для вашего устройства тесты). Например, Скрученный / скрученный / тестовый / . Конечно, сделать это пакет с Twisted / twisted / test / __ init __. Py . Поместите тесты в файлы вроде Twisted / twisted / test / test_internet.py .
  • добавьте Twisted / README и T wisted / setup.py для объяснения и установить свое ПО соответственно, если вы чувствуете себя хорошо.

Не :

  • помещайте свой исходный код в каталог называется src или lib . Это делает это сложно запустить без установки.
  • положить ваши тесты вне вашего Python пакет. Это затрудняет запуск тесты против установленной версии.
  • создать пакет, в котором есть только __ init __. Py , а затем поместите все свои код в __ init __. py . Просто сделай модуль вместо пакета, это проще.
  • попробуйте придумать волшебные хаки, чтобы Python мог импортируйте свой модуль или пакет без когда пользователь добавляет каталог содержащий его в свой путь импорта (либо через PYTHONPATH , либо через другой механизм). Вы не будете правильно обрабатывать все дела, и пользователи получат злится на тебя, когда твое программное обеспечение не работает в их среде.
4
ответ дан 5 December 2019 в 21:20
поделиться
Другие вопросы по тегам:

Похожие вопросы: