Импорт файлов из разных папок

У меня есть следующая структура папок.

application/app/folder/file.py

и я хочу импортировать некоторые функции из файла file.py в другой файл Python, который находится в

application/app2/some_folder/some_file.py

я пробовал

from application.app.folder.file import func_name

и некоторые другие различные попытки, но до сих пор я не мог правильно импортировать. Как я могу это сделать?

Ответ 1

По умолчанию вы не можете. При импорте файла Python ищет только текущий каталог, каталог, из которого выполняется сценарий точки входа, и sys.path который включает в себя такие места, как каталог установки пакета (на самом деле он немного сложнее, чем этот, но это охватывает большинство случаев).

Тем не менее, вы можете добавить к пути Python во время выполнения:

# some_file.py
import sys
# insert at 1, 0 is the script path (or '' in REPL)
sys.path.insert(1, '/path/to/application/app/folder')

import file

Ответ 2

Ничего плохого в:

from application.app.folder.file import func_name

Просто убедитесь, что folder также содержит __init__.py, это позволяет включать ее в пакет. Не уверен, почему другие ответы говорят о PYTHONPATH.

Ответ 3

Когда модули находятся в параллельных местах, как в вопросе:

application/app2/some_folder/some_file.py
application/app2/another_folder/another_file.py

Это сокращение делает один модуль видимым для другого:

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

Ответ 4

Я думаю, что специальным способом было бы использовать переменную окружения PYTHONPATH как описано в документации: Python2, Python3

# Linux & OSX
export PYTHONPATH=$HOME/dirWithScripts/:$PYTHONPATH

# Windows
set PYTHONPATH=C:\path\to\dirWithScripts\;%PYTHONPATH%

Ответ 5

Первый импорт sys

 import sys

Второй добавить путь к папке

sys.path.insert(0, '/the/folder/path/name-folder/')

Третий. Сделайте пустой файл с именем __ init __.py в вашем подкаталоге (это говорит, что Python это модуль)

  • name-file.py
    • имя-папки
      • __ init __.py
      • name-module.py

Четвертый импорт модуля внутри папки

from name-folder import name-module

Ответ 6

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

Для этого вы меняете это:

from application.app.folder.file import func_name

к этому:

from .application.app.folder.file import func_name

Добавляя точку, вы говорите, что смотрите в этой папке для папки приложения вместо поиска в каталоге Python.

Ответ 7

Ответы здесь недостаточны, это проверено на Python 3.6

С этой структурой папок:

main.py
|
---- myfolder/myfile.py

Где myfile.py имеет контент:

def myfunc():
    print('hello')

Оператор import в main.py:

from myfolder.myfile import myfunc
myfunc()

и это будет печатать привет.

Ответ 8

Из того, что я знаю, добавьте файл __init__.py непосредственно в папку функций, которые вы хотите импортировать, выполнит задание.

Ответ 9

Учитывая application как корневой каталог для вашего проекта python, создайте пустой __init__.py файл в папках application, app и folder. Затем в some_file.py введите следующие изменения, чтобы получить определение func_name:

import sys
sys.path.insert(0, r'/from/root/directory/application')

from application.app.folder.file import func_name ## You can also use '*' wildcard to import all the functions in file.py file.
func_name()

Ответ 10

Работала для меня в python3 на linux

import sys  
sys.path.append(pathToFolderContainingScripts)  
from scriptName import functionName #scriptName without .py extension  

Ответ 11

Я столкнулся с такой же проблемой, особенно при импорте нескольких файлов, вот как мне удалось ее преодолеть.

import os, sys

from os.path import dirname, join, abspath
sys.path.insert(0, abspath(join(dirname(__file__), '..')))

from root_folder import file_name

Ответ 12

Попробуйте относительный импорт Python:

from ...app.folder.file import func_name

Каждая ведущая точка - это еще один более высокий уровень в иерархии, начиная с текущего каталога.


Проблемы? Если это не работает для вас, вы, вероятно, получаете немного из-за того, что у меня есть относительный импорт. Прочтите ответы и комментарии для получения более подробной информации. Как исправить "Попытка относительного импорта в непакту" даже с __init__.py

Подсказка: есть __init__.py на каждом уровне каталога. Вам может понадобиться python -m application.app2.some_folder.some_file (оставляющий.py), который вы запускаете из каталога верхнего уровня или имеете этот каталог верхнего уровня в PYTHONPATH. Уф!

Ответ 13

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

Вот пример. Сначала импортируемый файл с именем foo.py:

def announce():
    print("Imported!")

Код, который импортирует файл выше, в значительной степени вдохновлен примером в документации:

import importlib.util

def module_from_file(module_name, file_path):
    spec = importlib.util.spec_from_file_location(module_name, file_path)
    module = importlib.util.module_from_spec(spec)
    spec.loader.exec_module(module)
    return module

foo = module_from_file("foo", "/path/to/foo.py")

if __name__ == "__main__":
    print(foo)
    print(dir(foo))
    foo.announce()

Выход:

<module 'foo' from '/path/to/foo.py'>
['__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'announce']
Imported!

Обратите внимание, что имя переменной, имя модуля и имя файла не обязательно должны совпадать. Этот код все еще работает:

import importlib.util

def module_from_file(module_name, file_path):
    spec = importlib.util.spec_from_file_location(module_name, file_path)
    module = importlib.util.module_from_spec(spec)
    spec.loader.exec_module(module)
    return module

baz = module_from_file("bar", "/path/to/foo.py")

if __name__ == "__main__":
    print(baz)
    print(dir(baz))
    baz.announce()

Выход:

<module 'bar' from '/path/to/foo.py'>
['__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'announce']
Imported!

Программный импорт модулей был представлен в Python 3.1 и дает вам больше контроля над тем, как импортируются модули. Обратитесь к документации для получения дополнительной информации.

Ответ 14

Использование sys.path.append с абсолютным путем не идеально при перемещении приложения в другие среды. Использование относительного пути не всегда работает, потому что текущий рабочий каталог зависит от того, как был вызван скрипт.

Поскольку структура папок приложения фиксирована, мы можем использовать os.path, чтобы получить полный путь к модулю, который мы хотим импортировать. Например, если это структура:

/home/me/application/app2/some_folder/vanilla.py
/home/me/application/app2/another_folder/mango.py

И скажем, вы хотите импортировать модуль "манго". Вы можете сделать следующее в vanilla.py:

import sys, os.path
mango_dir = (os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))
+ '/another_folder/')
sys.path.append(mango_dir)
import mango

Конечно, вам не нужна переменная mango_dir.

Чтобы понять, как это работает, посмотрите на этот пример интерактивного сеанса:

>>> import os
>>> mydir = '/home/me/application/app2/some_folder'
>>> newdir = os.path.abspath(os.path.join(mydir, '..'))
>>> newdir
    '/home/me/application/app2'
>>> newdir = os.path.abspath(os.path.join(mydir, '..')) + '/another_folder'
>>> 
>>> newdir
'/home/me/application/app2/another_folder'
>>> 

И проверьте документацию os.path.

Ответ 15

Это работает для меня в окнах

# some_file.py on mainApp/app2 
import sys
sys.path.insert(0, sys.path[0]+'\\app2')

import some_file

Ответ 16

Я довольно особенный: я использую Python с Windows!

Я просто заполняю информацию: как для Windows, так и для Linux, как относительный, так и абсолютный путь работают в sys.path (мне нужны относительные пути, потому что я использую свои скрипты на нескольких ПК и в разных основных каталогах).

И при использовании Windows оба \ и / могут использоваться как разделители для имен файлов, и, конечно же, вы должны удвоить \ в строки Python,
некоторые допустимые примеры:

sys.path.append('c:\\tools\\mydir')
sys.path.append('..\\mytools')
sys.path.append('c:/tools/mydir')
sys.path.append('../mytools')

(примечание: Я думаю, что / более удобен, чем \, событие, если оно меньше "родной Windows", потому что оно совместимо с Linux и проще писать и копировать в проводник Windows)

Ответ 17

Если целью загрузки модуля из определенного пути является помощь вам при разработке настраиваемого модуля, вы можете создать символическую ссылку в той же папке теста script, которая указывает на корень пользовательского модуля модуль. Эта ссылка на модуль будет иметь приоритет над любыми другими модулями, установленными с тем же именем для любого script, запускаемого в этой папке.

Я тестировал это на Linux, но он должен работать в любой современной ОС, поддерживающей символические ссылки.

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

Ответ 18

Я работал над проектом a что я хотел пользователей установить через pip install a следующий список файлов:

.
├── setup.py
├── MANIFEST.in
└── a
    ├── __init__.py
    ├── a.py
    └── b
        ├── __init__.py
        └── b.py

setup.py

from setuptools import setup

setup (
  name='a',
  version='0.0.1',
  packages=['a'],
  package_data={
    'a': ['b/*'],
  },
)

MANIFEST.in

recursive-include b *.*

/init.py

from __future__ import absolute_import

from a.a import cats
import a.b

а /a.py

cats = 0

a/b/init.py

from __future__ import absolute_import

from a.b.b import dogs

A/B/b.py

dogs = 1

Я установил модуль, запустив следующее из каталога с MANIFEST.in:

python setup.py install

Затем из совершенно другого места в моей файловой системе /moustache/armwrestle я смог запустить:

import a
dir(a)

Это подтвердило, что a.cats действительно равнялось 0, а abdogs действительно равнялось 1, как и предполагалось.

Ответ 19

В моем случае у меня был класс для импорта. Мой файл выглядел так:

# /opt/path/to/code/log_helper.py
class LogHelper:
    # stuff here

В свой основной файл я включил код через:

import sys
sys.path.append("/opt/path/to/code/")
from log_helper import LogHelper

Ответ 20

Вы можете обновить оболочку Python, нажав f5 или перейдите в Run- > Run Module. Таким образом, вам не нужно менять каталог, чтобы что-то прочитать из файла. Python автоматически изменит каталог. Но если вы хотите работать с разными файлами из другого каталога в оболочке Python, вы можете изменить каталог в sys, как ранее сказал Кэмерон.

Ответ 21

Таким образом, я просто щелкнул правой кнопкой мыши по моей среде IDE и добавил новую folder и задавался вопросом, почему я не смог импортировать ее. Позже я понял, что мне нужно щелкнуть правой кнопкой мыши и создать пакет Python, а не классическую папку с файловой системой. Или метод post-mortem, добавляющий __init__.py (что делает python относиться к папке файловой системы как к пакету), как упоминалось в других ответах. Добавляя этот ответ здесь, на всякий случай кто-то поехал по этому маршруту.

Ответ 22

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

import importlib

scriptName = 'Snake'

script = importlib.import_module('Scripts\\.%s' % scriptName)

В этом примере есть main.py, который представляет собой приведенный выше код, затем папку с именем Scripts, и затем вы можете вызывать все, что вам нужно, из этой папки, изменив переменную scriptName. Затем вы можете использовать script для ссылки на этот модуль. например, если у меня есть функция Hello() в модуле Snake, вы можете запустить эту функцию следующим образом:

script.Hello()

Я проверил это в Python 3.6

Ответ 23

sys.path.insert(0, '/path/to/application/app/folder')