Импорт из вложенной папки python

#python #python-3.x #python-import

#python #python-3.x #python-импорт

Вопрос:

Структура моего проекта следующая. Внутри api.py мне нужны некоторые функции, написанные на верхнем уровне.

 Project1
├── model.py 
├── audio_utils.py
├── audio.py 
└── backend
     ├── static
     │      ├──js
     │      ├──img
     └── api.py

  

Почему я не могу импортировать внутри api.py функции на верхнем уровне?
Когда я пытаюсь сделать:

 from audio_utils import *
  

Я получил следующее:

  No module named 'audio_utils'
  

Комментарии:

1. Вы пробовали from Project1.audio_utils import * ?

2. Можете ли вы проверить, находится ли проект path в PYTHONPATH python -c "import sys;print(sys.path);"

Ответ №1:

Модули импортируются из префиксов путей, указанных в sys.path . Обычно '' это означает, что будут загружены модули из текущего рабочего каталога. (https://docs.python.org/3/tutorial/modules.html#packages )

Я думаю, что вы начинаете интерпретировать Python, находясь в backend каталоге. Тогда я думаю, что нет никакого способа получить доступ к модулям в верхнем каталоге — даже с .. помощью (https://realpython.com/absolute-vs-relative-python-imports/#syntax-and-practical-examples_1 ) если вы не измените sys.path , что было бы действительно грязным решением.

Я предлагаю вам создать __init__.py файлы, чтобы указать, что каталоги, содержащие их, являются пакетами Python:

 Project1
├── model.py 
├── audio_utils.py
├── audio.py 
└── backend
     |-- __init__.py
     ├── static
     │      ├──js
     │      ├──img
     └── api.py
  

И всегда запускайте интерпретацию из Project1 каталога. Таким образом, вы должны иметь возможность импортировать любой подобный модуль:

 import model
from backed import api
import audio_utils
  

независимо от того, в каком модуле Project1 вы это пишете. Будет проверен текущий каталог интерпретатора.

Обратите внимание, что существует также PYTHONPATH переменная env, которую вы можете использовать в своих интересах.

Обратите внимание, что для публикации вашего проекта рекомендуется поместить все модули в пакет (другими словами: не помещайте модули на верхний уровень). Это помогает предотвратить конфликты имен. Я думаю, это может помочь вам понять: https://realpython.com/pypi-publish-python-package /

Комментарии:

1. Спасибо! Я создал новый файл в верхней папке, затем импортировал серверную часть формы api и запустил сервер как обычно. Раньше это не работало, потому что мой «основной» был внутри api.py

Ответ №2:

У вас есть __init__.py файлы в обоих каталогах, верно?

Попробуйте from ..audio_utils import *

Комментарии:

1. Добро пожаловать в StackOverflow! Хотя это может помочь автору, гораздо более ценным является более подробный ответ, объясняющий, почему это помогает.

Ответ №3:

Если вы создаете структуру каталога таким образом:

 $ tree
.
├── bar
│   ├── den.py
│   └── __init__.py  # This indicates the bar is python package.
└── baz.py

1 directory, 3 files
$ cat bar/den.py 
import baz
  

Затем в каталоге, содержащем bar/ и baz.py (верхний уровень), вы можете запустить интерпретацию Python и использовать абсолютный импорт:

 In [1]: import bar.den                                                                                                                                                                        

In [2]: import baz                                                                                                                                                                            

In [3]: bar.den.baz                                                                                                                                                                           
Out[3]: <module 'baz' from '/tmp/Project1/baz.py'>
  

Как вы можете видеть, мы смогли импортировать bar.den , который также может импортировать baz с верхнего уровня.