Как импортировать модули из родительского подкаталога - PullRequest
4 голосов
/ 28 июня 2019

Я хочу импортировать class из файла Python в каталог в родительском каталоге. Это моя текущая структура папок:

│   run_simulation_from_parent.py
│   __init__.py
│
├───.vscode
│       launch.json
│       settings.json
│
├───mod
│   │   mods.py
│   │   __init__.py
│   │
│   └───__pycache__
│           __init__.cpython-37.pyc
│
├───sim
│   │   run_simulation.py
│   │   __init__.py
│   │
│   └───__pycache__
│           __init__.cpython-37.pyc
│
└───__pycache__
        __init__.cpython-37.pyc

Файл mod/mods.py содержит следующий класс:

class Objective:
    """Objective function class"""

    def __init__(self, x):
        self.x = x

Файл sim/run_simulation.py содержит:

from mod.mods import Objective

x = 5
obj = Objective(x)

Когда я пытаюсь запустить это, я получаю следующую ошибку:

  File "sim/run_simulation.py", line 1, in <module>
    from mod.mods import Objective
ModuleNotFoundError: No module named 'mod'

В Visual Studio код выполняет автозаполнение, когда я начинаю набирать mod.mods и import Objective

Когда я запускаю run_simulation_from_parent.py со следующим содержимым, у меня нет проблем:

from mod.mods import Objective

x = 5
obj = Objective(x)

print(obj.x)

Как я могу сделать это из каталога sim? Я уже попробовал следующее:

  1. Используйте from ..mod.mods import Objective для run_simulation.py
  2. Используйте init .py файлы со следующим содержимым: import os, sys sys.path.append(os.path.dirname(os.path.realpath(__file__)))

  3. Без файлов __init__.py

Редактировать: я запускаю файл из кода Visual Studio, где я запускаю в родительском каталоге. Я также пытался из командной строки в windows из папки sim, где я использовал

python run_simulation.py

Ответы [ 3 ]

2 голосов
/ 28 июня 2019

Способ работы с импортом внутри проекта заключается в установке проекта в редактируемом режиме . Таким образом, все файлы смогут найти друг друга, всегда начиная с корневого каталога вашего проекта.

Чтобы сделать это, выполните следующие действия:

1) напишите файл setup.py и добавьте его в корневую папку вашего проекта - ему вообще не нужно много информации:

# setup.py
from setuptools import setup, find_packages

setup(name='MyPackageName', version='1.0.0', packages=find_packages())

2) установить пакет в редактируемом режиме (в идеале из виртуальной среды). С терминала в папке вашего проекта напишите

$ pip install -e .

Обратите внимание на точку - это означает «установить пакет из текущего каталога в редактируемом режиме».

3) Ваши файлы внутри проекта теперь могут находить друг друга , всегда начиная с корня проекта. Для импорта Objective, например, вы пишете:

from mod.mods import Objective

Это будет верно для импорта Objective для любого файла, независимо от того, где он находится в структуре проекта .

Как я уже сказал, вы должны использовать для этого виртуальную среду, чтобы pip не устанавливал ваш пакет в вашу основную установку Python (что может быть грязно, если у вашего проекта много зависимостей).

Мой любимый инструмент для этого - pipenv . При его использовании замените команду терминала на

$ pipenv install -e .

Чтобы ваш проект был добавлен в Pipfile.

1 голос
/ 28 июня 2019

Я нашел одно решение, добавив его в системный путь:

import os
import os.path
import sys

sys.path.append(os.getcwd() + "\\mod")

from mods import Objective

x = 5
obj = Objective(x)

print(obj.x)

Это работает, но я не могу себе представить, что это действительно так, как задумано ..

Редактировать: следующее является более общим:

import os
import sys

sys.path.append(os.getcwd())

from mod.mods import Objective

x = 5
obj = Objective(x)

print(obj.x)

Что-то подсказывает мне, что это можно сделать проще, но я не знаю, как ..

1 голос
/ 28 июня 2019

Используйте from ..mod.mods import Objective и сохраните все __init__.py файлы.

...