Импорт файлов из другой папки

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

application / app / folder / file.py

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

application / app2 / some_folder / some_file.py

Я пробовал

из application.app.folder.file import func_name

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

Комментарии к вопросу (2)

По умолчанию вы не можете. При импорте файла 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
Комментарии (18)

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

from application.app.folder.file import func_name

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

Комментарии (18)

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

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

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

import sys
sys.path.append('../')
Комментарии (3)

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

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

# Windows
set PYTHONPATH=C:\path\to\dirWithScripts\;%PYTHONPATH%
Комментарии (2)

Первые импортные системы

 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
Комментарии (1)

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

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

из application.app.folder.file import func_name

к этому:

from .application.app.folder.file import func_name

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

Комментарии (1)

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

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

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

Где myfile.py имеет содержимое:

def myfunc():
    print('hello')

Заявление об импорте в main.py:

from myfolder.myfile import myfunc
myfunc()

и это напечатает привет .

Комментарии (11)

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

Комментарии (2)

Рассматривая 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()
Комментарии (1)

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

import sys  
sys.path.append(pathToFolderContainingScripts)  
from scriptName import functionName #scriptName without .py extension  
Комментарии (1)

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

import os, sys

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

from root_folder import file_name
Комментарии (2)

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

from ...app.folder.file import func_name

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


Проблемы? Если это не работает для вас, то вы, вероятно, получаете немного от относительного импорта многих гочей. Читайте ответы и комментарии для более подробной информации: https://stackoverflow.com/questions/11536764/how-to-fix-attempted-relative-import-in-non-package-even-with-init-py

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

Комментарии (0)

В 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()

Выход:


['__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()

Выход:


['__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'announce']
Imported!

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

Комментарии (1)

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

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

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

И скажем, что вы хотите импортировать модуль «Манго». Вы можете сделать следующее на vanil.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.

Комментарии (0)

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

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

import some_file
Комментарии (0)

Я особенный: я использую 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)

Комментарии (1)

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

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

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

Комментарии (0)

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

.
├── setup.py
├── MANIFEST.in
█─ ─ а
    ├── __init__.py
    ├──.py
    █── б
        ├── __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 *.*

a / init.py

from __future__ import absolute_import

from a.a import cats
import a.b

а / а.пи

cats = 0

a / b / init.py

from __future__ import absolute_import

from a.b.b import dogs

а / б / б.пи

dogs = 1

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

python setup.py install

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

import a
dir(a)

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

Комментарии (0)

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

# /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
Комментарии (2)

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

import importlib

scriptName = 'Snake'

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

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

script.Hello()

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

Комментарии (0)