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

762 Ivan [2010-12-08 05:07:00]

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

application/app/folder/file.py

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

application/app2/some_folder/some_file.py

я пробовал

from application.app.folder.file import func_name

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

python python-import importerror


21 ответ


868 Cameron [2010-12-08 05:12:00]

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

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

# some_file.py
import sys
sys.path.insert(0, '/path/to/application/app/folder')

import file

432 joey [2014-02-24 21:27:00]

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

from application.app.folder.file import func_name

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


48 slizb [2016-11-15 17:55:00]

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

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

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

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

34 Ax3l [2014-02-19 14:00:00]

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

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

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

22 Vaibhav Singh [2014-11-24 07:31:00]

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


18 danday74 [2018-02-19 06:22:00]

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

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

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

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

def myfunc():
    print('hello')

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

from myfolder.myfile import myfunc
myfunc()

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


16 ChandanK [2015-10-15 11:34:00]

Учитывая 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()

14 dsg38 [2016-08-16 18:24:00]

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

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

12 CianB [2017-02-11 03:29:00]

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

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

from application.app.folder.file import func_name

к этому:

from .application.app.folder.file import func_name

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


12 Alex Montoya [2018-05-22 21:48:00]

Первый импорт 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

11 Emeeus [2016-03-27 22:16:00]

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

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

import some_file

8 Zectbumo [2017-12-17 11:43:00]

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

from ...app.folder.file import func_name

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


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

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


6 Nagev [2017-10-04 19:05:00]

Использование 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.


5 geekobi [2017-03-18 15:36:00]

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


5 Timothy C. Quinn [2015-12-23 18:42:00]

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

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

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


1 mithunpaul [2018-07-27 04:27:00]

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


0 Erick Mwazonga [2018-10-01 10:00:00]

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

import os, sys

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

from root_folder import file_name

0 wecsam [2018-07-30 04:12:00]

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

Вот пример. Сначала файл, который нужно импортировать, называется foo.py:

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

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

import importlib, importlib.util, os.path

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, importlib.util, os.path

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 и дает вам больше контроля над тем, как модули импортируются. Дополнительную информацию см. В документации.


0 IOstream [2017-07-13 01:10:00]

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


0 schmudu [2017-11-30 03:15:00]

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

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

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

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

-2 Mickey Yang [2017-03-18 04:22:00]

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