Python Unittest: сбой из-за импорта из той же папки - PullRequest
0 голосов
/ 20 февраля 2019

вопрос кажется довольно тривиальным, но я не смог найти ни одного ответа на него в Интернете.Вот мои настройки:

project:
- src:
- - __init__.py (empty)
- - file1.py
- - file2.py
- test:
- - test1.py
- - test2.py
- - __init__.py (empty)

Теперь я хочу запустить

python -m unittest discover

из папки проекта.

В test1.py я импортирую и импортирую из своего первогоисходный файл:

from src.file1 import class1

Однако в file1.py я импортирую из другого:

from file2 import class2

Запуск unittest, как указано выше, приводит к:

[...]
    from file2 import class2
ModuleNotFoundError: No module named 'file2'

Что я здесь не так делаю?

Спасибо и хорошего дня!

1 Ответ

0 голосов
/ 20 февраля 2019

Вы должны полностью квалифицировать свой импорт, то есть вместо:

from file2 import class2

использовать

from .file2 import class2

заметить . после from.

Обновление: проверка:

(dev) go|c:\srv\tmp\unttst\project> tree
.
|-- src
|   |-- __init__.py
|   |-- file1.py
|   `-- file2.py
`-- test
    |-- __init__.py
    `-- test1.py

2 directories, 5 files

(dev) go|c:\srv\tmp\unttst\project> type src\file1.py

from .file2 import Class2

class class1:
    pass

(dev) go|c:\srv\tmp\unttst\project> type src\file2.py


class Class2:
    pass

(dev) go|c:\srv\tmp\unttst\project> type test\test1.py

from src.file1 import class1

(dev) go|c:\srv\tmp\unttst\project> python -m unittest discover

----------------------------------------------------------------------
Ran 0 tests in 0.000s

OK

(dev) go|c:\srv\tmp\unttst\project>

Обратите внимание, что я запускаю команду из каталога, где from src.xxx имеет смысл.

Обновление 2: Примечание: Python не предназначен для непосредственного запуска отдельных файлов в подкаталоге (то есть в качестве точки входа).Гвидо категорически против такого использования, поэтому вряд ли это изменится.Несмотря на то, что вы можете обойти это, сделать это правильно очень просто и стоит учиться.

Давайте сначала изменим src/file1.py на функцию main():

(dev) go|c:\srv\tmp\unttst\project> cat src\file1.py

from .file2 import Class2

class class1:
    pass


def main():
    print("hello from main")

Примечание: я не добавляю секцию if __name__=="__main__".

Правильный способ вызова этой функции из командной строки - сделать project "настоящим" пакетом.

A "настоящий "пакет создается путем добавления файла setup.py.Файлы setup.py могут содержать много полей, но для этого варианта использования необходимы только следующие:

(dev) go|c:\srv\tmp\unttst\project> cat setup.py

from setuptools import setup

setup(
    name="myproject",
    entry_points={
        'console_scripts': """
            run-file1 = src.file1:main
        """
    }
)

обратите внимание, что setup.py находится в папке project.

Далее вы устанавливаете пакет в режиме «разработки»:

(dev) go|c:\srv\tmp\unttst\project> pip install -e .

замечают . в конце.

entry_points .. console_scripts в файле setup.py имееттеперь создал новую команду оболочки для вас:

(dev) go|c:\srv\tmp\unttst\project> run-file1
hello from main

строка console_scripts

run-file1 = src.file1:main

говорит о создании команды оболочки с именем run-file, которая должна выполнить функцию main, найденную вsrc.file1.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...