2016-01-08 4 views
0

Учитывая эту простую структуруВзаимный импорт; Разница между Standart ИМПОРТ, в «от» и «как» синтаксис

/main.py 
/project/a.py 
/project/b.py 

main.py папки выполняется с помощью интерпретатора и содержит одну строку, import project.a.

a и b - это модули, им необходимо импортировать друг друга. Способ достижения этой цели будет

import project.[a|b] 

При работе с более глубокой вложенной структурой папок вы не хочешь, чтобы написать весь путь каждый раз, когда вы используете модуль, например,

import project.foo.bar 
project.foo.bar.set_flag(project.foo.bar.SUPER) 

Оба from project import [a|b] и import project.[a|b] as [a|b] результат ошибки импорта (при использовании в обоих, a и b).

Что нового между синтаксисом стандартного импорта и синтаксисом from или as? Почему для взаимного импорта работает только стандартный синтаксис?

И что еще более важно, существует простой и чистый способ импорта модулей, которые позволяют взаимный импорт и присваивать им более короткие имена (в идеале базовое имя модулей, например bar, в случае project.foo.bar)?

+0

Обратите внимание на [круглый вопрос импорта] (http://stackoverflow.com/q/744373/180709) и возвращайтесь с более подробной ошибкой, если она не решит вашу проблему. – zopieux

+0

@ Zopieux Я знаю, как работает система импорта, и нет ошибки. Я просто ищу способ импортировать модули и назначать им более короткие имена при импорте друг друга. – timakro

+0

Я думаю, что 'import a' и' import b' должны быть точными – danidee

ответ

1

Когда вы либо import project.a или from project import a, происходит следующее:

  1. Объект модуль project.a помещается в sys.modules. Это словарь, который сопоставляет имя каждого модуля с его объектом модуля, поэтому у вас будет sys.modules = {..., 'p.a': <module 'p.a' from '.../project/a.py'>, ...}.
  2. Выполнен код модуля.
  3. Атрибут a добавлен в project.

Теперь, вот разница между import project.a и from project import a:

  • import project.a просто ищет sys.modules['project.a']. Если он существует, он связывает имя project с использованием sys.modules['project'].
  • from project import a ищет sys.modules['project'], а затем проверяет, имеет ли модуль project атрибут a.

    Вы можете думать о from project import a как эквивалент двух следующих строк:

    import project.a # not problematic 
    a = project.a  # causes an error 
    

Вот почему вы видите только исключение при выполнении from project import a: sys.modules['project.a'] существует, но project еще не имеют a атрибут.


Быстрое решение заключается в том, чтобы просто избегать циркулярного импорта. Но если вы не можете, то обычные стратегии:

  • Импорт как можно позже. Предположим, что ваш a.py выглядит следующим образом:

    from project import b 
    
    def something(): 
        return b.something_else() 
    

    Rewrite это следующим образом:

    def something(): 
        from project import b 
        return b.something_else() 
    

    Конечно, вам придется повторить import сек во всех ваших функций.

  • Используйте ленивый импорт. Ленивый импорт не является стандартной функцией Python, но вы можете найти множество реализаций. Они работают с использованием принципа «импорт как можно ближе», но они добавляют некоторый синтаксический сахар, чтобы вы могли писать меньше кода.

  • Чит, и использовать sys.modules, как это:

    import sys 
    import project.a 
    a = sys.modules['project.a'] 
    

    Очень непитоновский, но работает.

Очевидно, что бы решение вы ни выбрали, вы не будете иметь возможность получать доступ атрибуты из a или b до модулей, были полностью загружены.

+0

Это не то, что я просил, я ищу способ сделать импорт формы 'from', работающей с« взаимным импортом », как я их называю, например. 'a' импортирует' b' и наоборот. – timakro

+0

@timgame: извините, но я не могу понять. Что такое «взаимный импорт»? Возможно, вы имеете в виду круговой импорт? Если да, то что из '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' –

+0

Попробуйте установить мой вопрос в python 3.x. Я в основном ищу способ запуска этой установки без необходимости писать 'project. [A | b]' каждый раз. – timakro