Как работает импорт в IPython

Я немного сбит с толку тем, как именно операторы импорта работают в IPython. Я ничего не нашел через веб-поиски.

Неявный относительный импорт работает с Python 2, но я не знаю, так ли это по-прежнему с IPython для Python 3.

Относительный импорт с использованием точечного синтаксиса вообще не работает:

In [6]: ls 
dsp/  __init__.py  __init__.pyc  utils/

In [7]: from .utils import capture
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-7-e7d50007bdd1> in <module>()
----> 1 from .utils import capture

ValueError: Attempted relative import in non-package

импорт модулей, использующих точечный синтаксис, кажется невозможным:

In [8]: cd utils
/home/user/workspace/mypkg/mypkg/utils

In [9]: ls
capture/  capture.py  capture.pyc  cext/  __init__.py  __init__.pyc

In [10]: from capture import Capture
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-10-8c31c76d052d> in <module>()
----> 1 from capture import Capture

/home/user/workspace/mypkg/mypkg/utils/capture.py in <module>()
     17 import tarfile
     18 import re
---> 19 from .. import utils
     20 from . import flprint
     21 from select import poll

ValueError: Attempted relative import in non-package

Есть ли где-нибудь краткая документация по этому поводу?


person orodbhen    schedule 13.08.2014    source источник
comment
Импорт IPython — это обычный импорт Python, но запуск его внутри пакета проблематичен, потому что Python не рассматривает рабочий каталог как пакет. cd вверх на пару уровней, чтобы можно было сделать from mypkg.utils.capture import Capture, и он должен себя вести.   -  person Thomas K    schedule 13.08.2014
comment
Я думаю, что вижу. Я путаю текущий рабочий каталог с расположением модуля в иерархии пакетов.   -  person orodbhen    schedule 15.08.2014
comment
Да, from . import blah работает, только если вы находитесь в пакете. Он не просто просматривает каталог, где бы ни находился этот файл.   -  person Thomas K    schedule 15.08.2014


Ответы (1)


Проблема в том, что я импортировал модуль из более низкой позиции в иерархии пакетов, чем используется в операторе импорта модуля. Итак, если я перейду в каталог utils и запущу

from capture import Capture

затем захват становится верхним уровнем иерархии. Таким образом, оператор импорта в модуле захвата

from .. import utils

выходит за пределы верхнего уровня. Python не знает, к чему относится «..», потому что модули не знают, к какому пакету они принадлежат. Если я вернусь обратно в каталог mypkg, у меня возникнет та же проблема.

In [13]: cd ..
/home/user/workspace/myproj/mypkg

In [14]: from utils import capture
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-14-c87f26b2171d> in <module>()
----> 1 from utils import capture

/home/user/workspace/myproj/mypkg/utils/capture.py in <module>()
    18 import re
    19 import zmq
---> 20 from .. import utils
    21 from . import flprint
    22 from select import poll

ValueError: Attempted relative import beyond toplevel package

В данном случае utils — это верхний уровень, поэтому

from . import flprint

будет работать, но

from .. import utils

не будет работать.

Мне нужно переместить еще один каталог вверх:

In [19]: cd ..
/home/user/workspace/myproj

In [20]: from mypkg.utils import capture

In [21]: cap = capture.Capture

IPython может импортировать пакеты и модули, расположенные в текущем рабочем каталоге или из каталогов в пути импорта. Я могу добавить пакет в путь импорта, чтобы иметь возможность импортировать из любого рабочего каталога.

In [23]: import sys

In [24]: sys.path.append('/home/user/workspace/myproj')

In [25]: cd
/home/user

In [26]: from mypkg.utils import capture

Вы можете использовать sys.path.append, чтобы сделать ваш модуль «самоосознающим», но, как указано в alpha_989, это потенциально может привести к конфликтам имен. Однако это полезный обходной путь при выполнении работы внутри иерархии пакетов из сеанса интерактивного терминала.

person orodbhen    schedule 14.08.2014
comment
Пара вопросов: - person alpha_989; 10.02.2018
comment
если вы добавите sys.path к пути Python, и если есть 2 модуля с одинаковым именем, но расположенные в разных каталогах, какой из этих модулей будет найден первым? Тогда вам нужно знать имена всех модулей, которые уже используются, чтобы не вызвать конфликт имен при написании программы? - person alpha_989; 10.02.2018
comment
Гипотеза, по-видимому, заключается в том, что Python не знает о существовании пакета utils, когда вы запускаете файл из utils/capture, поэтому вам нужно пройти уровень up, поэтому python знает, что utils — это пакет. Когда мы поднимаемся на уровень вверх в каталог mypkg и имеем from .. import utils в capture.py, есть init.py< /i> в текущем рабочем каталоге, который должен быть виден Python. Тогда почему это все еще не работает, когда мы выполняем from .. import capture работу, когда запускаем/импортируем захват, находясь в каталоге mypkg? - person alpha_989; 10.02.2018
comment
В одном каталоге есть capture_folder и _capture.py. Откуда python знает, что он должен загружать модуль capture.py, а не каталог capture? - person alpha_989; 10.02.2018
comment
@ alpha_989 Первый вопрос: я считаю, что это правильно. Поэтому используйте относительные пути при написании модулей пакетов, но sys.path полезен при работе внутри иерархии пакетов из интерактивного сеанса. Второй вопрос: потому что интерпретатору Python все равно, где вы находитесь. Он интерпретирует .. со ссылкой на ваш оператор импорта, а не на вашу позицию в файловой иерархии. Вы сказали, что utils находится наверху, поэтому любая ссылка на .. должна быть на два уровня ниже. - person orodbhen; 11.02.2018
comment
@ alpha_989 Третий вопрос: пакет (то есть папка) будет иметь предпочтение. См. это сообщение. Отличные вопросы. Спасибо, что спросили их. Импорт немного сложнее. - person orodbhen; 11.02.2018
comment
Спасибо, что указали на этот пост. Это не мой пост, но кто-то другой указал мне на это. Вам может быть полезен этот пост: chrisyeh96.github.io /2017/08/08/ - person alpha_989; 13.02.2018