Python 3: импорт функции из файла Python в родительском каталоге

1

Я новичок в модульном тестировании и пытаюсь создать свой первый файл модульных тестов в Python 3. Поэтому у меня есть следующая действительно элементарная структура папок, просто имитирующая онлайн-курс.

D:\Projects\Projects\unit_testing_course  # parent dir absolute path

unit_testing_course/                      # root/parent folder
    first_project.py                      # has a function called avg() 
    tests/                                
        test_first_project.py             # I want to import avg() into this file

test_first_project.py - это файл, который я использую для модульного тестирования, и я хочу импортировать функцию avg() из first_project.py, который находится в родительском каталоге над ним.

У меня Windows 10, у меня открыт git bash по следующему пути: '/d/Projects/Projects/unit_testing_course' (т.е. родительский каталог, содержащий first_project.py, модуль/функцию, которую я пытаюсь импортировать в test_first_project.py файл в дочернем каталоге tests). Я продолжаю выполнять python tests/test_first_project.py

Я быстро обнаружил, что не могу использовать что-то вроде "from.. import first_project" или "from.. import avg", что приводит к сообщению об ошибке "ValueError: попытка относительного импорта за пределы пакета верхнего уровня".

Таким образом, читая документацию, я получаю, что и from, и import являются инструкциями, предназначенными для работы с модулями или пакетами. https://docs.python.org/3/tutorial/modules.html

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

Модуль - это файл, содержащий определения и операторы Python. Имя файла - это имя модуля с добавленным суффиксом .py. Внутри модуля имя модуля (в виде строки) доступно как значение глобальной переменной __name__. "

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

эта ссылка на документацию полезна для объяснения сценария, в котором у вас есть модуль в текущем каталоге, из которого вы запускаете оболочку программы /python, и вы просто пытаетесь импортировать функцию из этого модуля в эту программу.

Но в этом случае кажется, что нам нужно сказать Python, что нужно искать модуль с именем 'first_project' в определенном каталоге, родительском каталоге файла test_first_project.py. Я посмотрел раздел о путях поиска модулей, https://docs.python.org/3/tutorial/modules.html#the-module-search-path

Когда импортируется модуль с именем "спам", интерпретатор сначала ищет встроенный модуль с таким именем. Если он не найден, он ищет файл с именем spam.py в списке каталогов, заданных переменной sys.path. После инициализации программы на Python могут изменять sys.path. Каталог, содержащий выполняемый скрипт, помещается в начало пути поиска, перед стандартным путем к библиотеке.

Тогда я попробовал...

import sys
import os
p_dir_path = os.path.abspath('../')
sys.path.append(p_dir_path)
from  first_project import avg

Который до сих пор получает то же сообщение об ошибке "ValueError: попытка относительного импорта за пределы пакета верхнего уровня". Я надеялся, что изменение sys.path программно может изменить ситуацию...

Так что же мне нужно сделать для того, чтобы импортировать модуль из родительского каталога? Или... это невозможно сделать в Python? Нужно ли мне использовать пакет вместо модуля (т.е. мне нужно создать init.py в моем родительском каталоге)?

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

  • 0
    Запустите его из родительского каталога: python tests/test_first_project.py или просто python -m unittest . Возможно, понадобится tests/__init__.py .
  • 0
    Как ни странно, я уже этим занимаюсь. У меня есть git bash, открытый для / d / Projects / Projects / unit_testing_course, продолжаю использовать 'python tests / test_first_project.py', но я получаю эти ошибки.
Показать ещё 2 комментария
Теги:
python-3.x

1 ответ

0

Вы должны установить переменную PYTHONPATH соответствии с вашим проектом. В unit_testing_course, запустите

export PYTHONPATH=$(pwd)

в твоей раковине. И рассмотрим следующий код:

first_project.py

def avg(l):
    return sum(l)/len(l) if len(l) > 0 else 0

tests/test_first_project.py

import unittest 
from first_project import avg

class Test(unittest.TestCase):
    ...

tests/__init__.py

from .test_first_project import *

запуск python -m unittest tests будет работать как python -m unittest tests (при условии, что python указывает на желаемую версию python). Вы также можете использовать virtualenv и изменить его venv/bin/activate чтобы автоматически выполнить эту настройку пути. Когда ваш проект продолжает расти, я рекомендую иметь в базе две отдельные директории - одну для самого проекта и одну для тестов. Затем используйте относительный импорт в каждом соответственно. Это позволит вашему проекту быть гибким, если вы решите упаковать его или использовать как подмодуль или что-то вроде этого.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню