Ответ 1
Проблема заключается в том, что я импортировал модуль из нижней позиции иерархии пакетов, чем используется в инструкции импорта модуля. Поэтому, если я записал cd в каталог utils и запустил
from capture import Capture
тогда захват становится верхним уровнем иерархии. Таким образом, оператор import в модуле захвата
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
, он может потенциально привести к конфликтам имен. Тем не менее, это полезное обходное решение при выполнении работы внутри иерархии пакетов с интерактивного сеанса терминала.