Набридло хаків 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" або подібне. Напевно, вам ніколи не потрібні інші команди, крім створення, активації та деактивації.
Після того як ви створили та активували віртуальне середовище, ваша консоль повинна вказати назву віртуальної середовища в дужках
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!
* Докладніші приклади setup.py див. У документах setuptools.
** Насправді ви можете розмістити своє віртуальне середовище де завгодно на жорсткому диску.
sys.path
хаки та прочитати єдине фактичне рішення, яке було розміщено дотепер (через 7 років!).