Устали от взлома sys.path?
Доступно множество sys.path.append
хаков, но я нашел альтернативный способ решения проблемы.
Резюме
- Оберните код в одну папку (например
packaged_stuff
)
- Используйте
setup.py
сценарий создания, где вы используете setuptools.setup () .
- Pip установить пакет в редактируемом состоянии с
pip install -e <myproject_folder>
- Импортировать используя
from packaged_stuff.modulename import function_name
Настроить
Отправной точкой является предоставленная вами файловая структура, помещенная в папку с именем myproject
.
.
└── myproject
├── api
│ ├── api_key.py
│ ├── api.py
│ └── __init__.py
├── examples
│ ├── example_one.py
│ ├── example_two.py
│ └── __init__.py
├── LICENCE.md
├── README.md
└── tests
├── __init__.py
└── test_one.py
Я назову .
корневую папку, и в моем примере она расположена по адресу C:\tmp\test_imports\
.
api.py
В качестве тестового примера давайте используем следующее ./api/api.py
def function_from_api():
return 'I am the return value from api.api!'
test_one.py
from api.api import function_from_api
def test_function():
print(function_from_api())
if __name__ == '__main__':
test_function()
Попробуйте запустить test_one:
PS C:\tmp\test_imports> python .\myproject\tests\test_one.py
Traceback (most recent call last):
File ".\myproject\tests\test_one.py", line 1, in <module>
from api.api import function_from_api
ModuleNotFoundError: No module named 'api'
Также попытка относительного импорта не сработает:
Использование from ..api.api import function_from_api
приведет к
PS C:\tmp\test_imports> python .\myproject\tests\test_one.py
Traceback (most recent call last):
File ".\tests\test_one.py", line 1, in <module>
from ..api.api import function_from_api
ValueError: attempted relative import beyond top-level package
меры
- Создайте файл setup.py в корневой каталог
Содержание для setup.py
будет *
from setuptools import setup, find_packages
setup(name='myproject', version='1.0', packages=find_packages())
- Используйте виртуальную среду
Если вы знакомы с виртуальными средами, активируйте одну и перейдите к следующему шагу. Использование виртуальных сред не является абсолютно обязательным, но они действительно помогут вам в долгосрочной перспективе (когда у вас более 1 проекта ..). Самые основные шаги (запустить в корневой папке)
- Создать виртуальную среду
- Активировать виртуальную среду
source ./venv/bin/activate
(Linux, macOS) или ./venv/Scripts/activate
(Win)
Чтобы узнать больше об этом, просто посмотрите в Google "Python Virtual Env Tutorial" или подобное. Возможно, вам никогда не понадобятся какие-либо другие команды, кроме создания, активации и деактивации.
После того, как вы создали и активировали виртуальную среду, ваша консоль должна дать имя виртуальной среды в скобках.
PS C:\tmp\test_imports> python -m venv venv
PS C:\tmp\test_imports> .\venv\Scripts\activate
(venv) PS C:\tmp\test_imports>
и ваше дерево папок должно выглядеть так **
.
├── myproject
│ ├── api
│ │ ├── api_key.py
│ │ ├── api.py
│ │ └── __init__.py
│ ├── examples
│ │ ├── example_one.py
│ │ ├── example_two.py
│ │ └── __init__.py
│ ├── LICENCE.md
│ ├── README.md
│ └── tests
│ ├── __init__.py
│ └── test_one.py
├── setup.py
└── venv
├── Include
├── Lib
├── pyvenv.cfg
└── Scripts [87 entries exceeds filelimit, not opening dir]
- pip установите ваш проект в редактируемое состояние
Установите пакет верхнего уровня, myproject
используя pip
. Хитрость заключается в использовании -e
флага при установке. Таким образом, он устанавливается в редактируемом состоянии, и все изменения, внесенные в файлы .py, будут автоматически включены в установленный пакет.
В корневом каталоге запустите
pip install -e .
(обратите внимание на точку, это означает «текущий каталог»)
Вы также можете увидеть, что он установлен с помощью pip freeze
(venv) PS C:\tmp\test_imports> pip install -e .
Obtaining file:///C:/tmp/test_imports
Installing collected packages: myproject
Running setup.py develop for myproject
Successfully installed myproject
(venv) PS C:\tmp\test_imports> pip freeze
myproject==1.0
- Добавьте
myproject.
в свой импорт
Обратите внимание, что вам придется добавлять myproject.
только в импорт, который не будет работать в противном случае. Импорт, который работал без setup.py
& pip install
будет работать, по-прежнему работает нормально. Смотрите пример ниже.
Проверьте решение
Теперь давайте проверим решение, используя api.py
определенные выше и test_one.py
определенные ниже.
test_one.py
from myproject.api.api import function_from_api
def test_function():
print(function_from_api())
if __name__ == '__main__':
test_function()
запустить тест
(venv) PS C:\tmp\test_imports> python .\myproject\tests\test_one.py
I am the return value from api.api!
* См. Документацию по setuptools для более подробных примеров setup.py.
** На самом деле вы можете поместить свою виртуальную среду в любое место на жестком диске.
sys.path
хаки и прочитать единственное актуальное решение, которое было опубликовано до сих пор (через 7 лет!).