Импорт Python из дочерних каталогов - PullRequest
0 голосов
/ 10 сентября 2018

Отказ от ответственности: после поиска по тоннам очень похожих каналов, которые в конечном итоге оказываются для решения немного другой проблемы, я предполагаю, что должен открыть новый вопрос (хотя я уверен, что ответ существуетгде-то -> укажите, если вы это знаете;)

Проблема: Я использую Python 2, я строю проект с этим деревом:

project
├── __init__.py
├── foo  
│   └── __init__.py
│   └── bar   
│       └── __init__.py
├── notebooks   
│   └── __init__.py
│   └── skript.py
└── test
    └── __init__.py
    └── foo   
        └── __init__.py
        └── bar   
            └── __init__.py
            └── file.py

Теперь я хочу загрузить test.foo.bar из project/notebooks/skript.py.Поэтому я делаю в этом сценарии

import sys
sys.path.append('../')

Если я тогда запусту

import test.foo.bar  # or: import test.foo

, python сообщит мне

ImportError: No module named foo.bar

(или ImportError: No module named foo соответственно).К счастью, import test не выдаёт ошибку, но если я тогда сделаю test.foo, то выбрасывается AttributeError: 'module' object has no attribute 'foo'.

Так что мне интересно, что здесь не так и как это исправить?


Редактировать

Также я попытался добавить это к skript.py

import sys
import os
MYDIR = os.path.dirname(os.path.abspath(__file__))
sys.path.append(os.path.join(MYDIR,'../test'))
sys.path.append(os.path.join(MYDIR,'../test/foo'))
sys.path.append(os.path.join(MYDIR,'../test/foo/bar')) #I am not sure this is entirely needed

, как было указано ниже.Тем не менее,

import test.foo.bar.file

или из файла импорта test.foo.bar просто дают

ImportError: No module named foo.bar

То же самое для

sys.path.append('../test/foo/bar')
import test.foo.bar.file

Я до сих пор не понимаю, что происходит не так

Ответы [ 3 ]

0 голосов
/ 10 сентября 2018

Вы используете IDE? Если это так, добавьте путь к интерпретатору Python в свойствах проекта для всех основных пакетов (foo, test, notebook). В противном случае попробуйте явно добавить пакет bar в путь sys, например:

import sys
import os
MYDIR = os.path.dirname(os.path.abspath(__file__))
sys.path.append(os.path.join(MYDIR,'test'))
sys.path.append(os.path.join(MYDIR,'test/foo'))
sys.path.append(os.path.join(MYDIR,'test/foo/bar')) #I am not sure this is entirely needed
0 голосов
/ 10 сентября 2018

Мессинг с sys.path редко бывает хорошей идеей.

Поскольку ваш план состоит в том, чтобы использовать foo и test из notebooks (которые, вероятно, будут содержать только записные книжки Jupyter), самым чистым решением будет установка foo и test в качестве пакетов.

Удалите __init__.py из каталога верхнего уровня и notebooks, так как вы не захотите их импортировать. Затем добавьте setup.py в каталог верхнего уровня. Поскольку ваши тесты относятся только к foo, вам следует либо переименовать их foo_test, либо переместить их в foo.

Минимальный setup.py будет выглядеть так

from setuptools import setup

setup(name='foo',
      version='0.1',
      description='descroption of fo',
      author='you',
      author_email='your@mail',
      packages=['foo','test_foo])

Тогда вы можете просто pip install -e . в вашем каталоге верхнего уровня, и он будет установлен в вашу текущую virtualenv. Если вы не используете virtualenvs, вам следует pip install --user -e .

0 голосов
/ 10 сентября 2018

Должен работать с

from test import foo

Но вы должны добавить __init__.py в каталог вашего проекта.

Для Python 3 это будет:

from .test import foo

Если вы используете точку перед именем папки, python ищет файл в том же каталоге, в котором находится файл, над которым вы работаете.

Извините за мой плохой английский.

...