9. Імпорти
Помилка, що виникла у версії 1 практичного завдання, спонукає нас детальніше розглянути роль оператора [import].

9.1. Скрипти [import_01]
Скрипт [imported] імпортуватиметься різними скриптами (які також називаються модулями):

# модуль імпортовано
# ця інструкція виконуватиметься щоразу, коли модуль імпортується
print("2")
# змінна, що належить до імпортованого модуля
x=4
Модуль виконується під час його імпорту. Отже, коли буде імпортовано модуль [imported]:
- відбудеться відображення рядка 3;
- змінна x у рядку 5 отримає своє значення;
Скрипт [main_01] має такий вигляд:
# імпортований модуль виконується
import imported
# використання змінної x з імпортованого модуля
print(imported.x)
- рядок 2: імпортується модуль [imported]. Це призведе до його виконання:
- буде виведено значення 2;
- створюється змінна x із значенням 4;
- рядок 4: використовується змінна x з імпортованого модуля;
У PyCharm повідомляється про помилку:
У [1] повідомлення PyCharm вказує, що модуль [imported] невідомий. З технічної точки зору це означає, що папка, яка містить модуль [imported], не входить до Python Path модуля PyCharm. Python Path — це сукупність папок, у яких шукаються імпортовані модулі. Щоб вирішити цю проблему, достатньо вказати [Sources root] як папку, у якій знаходиться модуль [imported], у даному випадку папку [import/01]:


Після цієї операції папка [import/01] додається до Python Path у Pycharm, і помилка зникає:

- у [1] папка [01] змінила колір;
- у [2-3] помилки більше немає;
Результати виконання такі:
Коментарі
- рядок 2 — це результат виконання імпортованого модуля;
- у рядку 3 відображається значення змінної x імпортованого модуля;
З цього прикладу слід винести важливе поняття: імпортований модуль (або скрипт) виконується.
Скрипт [main_02] має такий вигляд:
# імпортується змінна x з імпортованого модуля
from imported import x
# вона виводиться на екран
print(x)
- у рядку 2 ми бачимо інший синтаксис імпорту [from module import objet1, objet2, …]. Тут імпортується змінна [imported.x]. За цим синтаксисом змінна x стає змінною скрипта [main_02]. Більше не потрібно додавати префікс її модуля [imported];
- рядок 4: виводимо змінну x зі скрипта [main_02];
Результати виконання такі:
Скрипт [main_03] має такий вигляд:
# імпортується все, що є видимим з імпортованого модуля
from imported import *
# використовується змінна x з імпортованого модуля
print(x)
Запис [import *] у рядку 2 означає, що імпортуються всі видимі об’єкти з імпортованого модуля (змінні, функції).
Результати такі:
Скрипт [main_04] має такий вигляд:
# імпортуємо змінну x з імпортованого модуля
# і перейменовуємо її на y
from imported import x as y
# виводиться змінна y
print(y)
У рядку 3 показано, що можна імпортувати об’єкт з імпортованого модуля та надати йому псевдонім. Тут змінна [imported.x] стає змінною [main_04.y]. Результати такі самі, як і раніше.
9.2. Скрипт [import_02]

Імпортований модуль [module1.py] має такий вигляд:
# функція
def f1():
print("f1")
Імпортований модуль визначає функцію, що є типовим випадком.
Скрипт [main_01] має такий вигляд:
# імпорт
import module1
# виконання f1
module1.f1()
- у рядку 2 модуль імпортується. Він буде виконаний. У цьому випадку він нічого не виводить;
- рядок 4: виконується функція [f1] з імпортованого модуля;
Результати виконання такі:
Примітка: Щоб уникнути помилки PyCharm під час імпортування рядка 2, потрібно помістити папку, що містить [module1], у [Sources Root] з PyCharm:

У файлі [1] папка [02], розміщена в [Sources Root], стала синьою. Слід зауважити, що зазначена помилка не заважає правильному виконанню скриптів. Адже під час виконання скрипта [main_0x] папка скрипта автоматично додається до Python Path. Таким чином, скрипт [module1] знайдено. Відтепер, коли на знімку екрана папка виділена синім кольором, це означає, що її було додано до [Sources Root] з PyCharm.
Скрипт [main_02] має такий вигляд:
# імпорт
from module1 import f1
# виконання f1
f1()
- у рядку 2 імпортується функція [f1] з модуля [module1];
- у рядку 4 використовується функція f1;
Результати збігаються з результатами скрипта [main_01].
9.3. Скрипти [import_03]

Примітка: [03] знаходиться у папці [Sources Root] цього проєкту.
Нові скрипти імпортують модуль [module2], який не знаходиться в тій самій папці, що й вони.
Скрипт [module2] має такий вигляд:
# функція
def f2():
print("f2")
Отже, скрипт визначає функцію [f2].
Скрипт [main_01] має такий вигляд:
# імпорт модуля Class2
import dir1.module2
# виконання f2
dir1.module2.f2()
- рядок 2: використовується спеціальна нотація, щоб вказати, як знайти модуль [module2]. [dir1.module2] слід читати як шлях [dir1/module2]: щоб знайти [module2], слід почати з папки поточного скрипта [main_01], потім перейти до [dir1], і там знайти [module2]. Тут не слід забувати, що початковою точкою шляху є папка скрипта, який виконує імпорт;
- рядок 4: для виконання функції [f2] зі скрипта [module2];
Результати такі:
Рядок 2 — результат функції [f2].
Скрипт [main_02] має такий вигляд:
# імпорт модуля dir1.module2, який перейменовується
import dir1.module2 as module2
# виконання f2
module2.f2()
У рядку 2 модуль [dir1.module] перейменовано, щоб спростити написання рядка 4.
Скрипт [main_03] має такий вигляд:
# імпорт функції f2 з модуля dir1.module2
from dir1.module2 import f2
# виконання f2
f2()
Цього разу у рядку 2 імпортуємо лише функцію [f2], яка стає функцією скрипта [main_03] (рядок 4).
Усі ці скрипти працюють однаково добре як у контексті PyCharm, так і в консолі Python. Причина в тому, що в обох випадках папка, з якої виконується скрипт, у даному випадку папка [03], входить до Python Path. Отже, папка [dir1/module2] знайдена.
9.4. Скрипти [import_04]

Тут папки [dir1] та [dir2] були розміщені в папці [Sources Root] проекту PyCharm.
Першим імпортованим модулем є [module3]:
# функція
def f3():
print("f3")
Другий імпортований модуль — [module4]:
from module3 import f3
# функція
def f4():
f3()
print("f4")
- у рядку 1 імпортується функція [f3] з [module3]. Тут [module3] видно, оскільки його папку [dir1] було розміщено в [Sources Root];
- рядки 4–6: визначається функція [f4], яка викликає функцію [f3] з [module3];
Головний скрипт [main_01] має такий вигляд:
# імпортуємо module4
from module4 import f4
# виконання f4
f4()
- у рядку 2 імпортується модуль [module4]. Він є видимим, оскільки його папку [dir2] було розміщено в [Sources Root] модуля PyCharm;
- у рядку 4: виконання функції [f4] з [module4];
Результати виконання [main_01] у PyCharm такі:
Тепер запустимо [main_01] у терміналі (консолі) Python:

Результати такі:
Що сталося? Термінал Python не має жодного уявлення про Python Path та про [Sources Root] і PyCharm. Він має власний Python Path. У ньому завжди є папка скрипта, що виконується, у даному випадку скрипт [main_01]. Отже, він знає папку [import/04]. У виконуваному скрипті він знаходить рядок:
from module4 import f4
Інтерпретатор Python шукає [module4] у папках свого Python Path. Однак [module4] знаходиться не в [import/04] (який дійсно є в Python Path), а в [import/04/dir2], якого там немає. Звідси й виникає помилка.
Отже, ми маємо проблему, з якою вже стикалися раніше: скрипт, що коректно виконується в PyCharm, може давати збій у контексті терміналу Python. Це повторювана проблема, яку нам доведеться вирішити.
9.5. Скрипти [import_05]

Примітка: папки [dir1] та [dir2] додано до Python Path. Відразу зауважимо, що тут існує конфлікт: файли [module3] та [module4] будуть знайдені у двох місцях Python Path файлу PyCharm:
- у [import/04/dir1] та [import/05/dir1] для [module3];
- у [import/04/dir2] та [import/05/dir2] для [module4];
Тоді можна вилучити [import/04/dir1] та [import/04/dir2] з [Sources Root] проекту PyCharm. Виявляється, що в даному випадку [import/05/dir1] є копією [import/04/dir1] (те саме стосується [dir2]), тому проблем не виникає. Проте слід зауважити, що всередині самого файлу PyCharm потрібно звертати увагу на список папок у файлі [Sources Root], щоб уникнути конфліктів.
Скрипт [main_01] виглядає наступним чином:
import sys
# змінюємо sys.path, щоб включити до нього папки
# , що містять класи, які потрібно імпортувати
sys.path.append(".")
sys.path.append("./dir1")
sys.path.append("./dir2")
# імпортуємо module4
from module4 import f4
# виконання f4
f4()
Ми намагаємося вирішити проблему з Python Path. Нам потрібен такий, який працюватиме однаково добре як у PyCharm, так і в терміналі Python. Для цього ми виправимо це самостійно.
- рядки 4–6: додаємо папки [., ./dir1, ./dir2] до Python Path. Щоб це працювало, поточна папка під час виконання має бути папкою [import/05]. Це буде дотримано в PyCharm, але не обов’язково — у терміналі Python, як ми побачимо;
- рядок 8: імпортуємо [module4]. З огляду на те, що ми щойно зробили, його слід знайти в [./dir2];
Виконання у файлі PyCharm дає такі результати:
Тепер у терміналі Python:
(venv) C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\import\05>python main_01.py
f3
f4
У рядку 1 файл виконання — [import/05].
Тепер піднімемося на один рівень вище в дереві [import/05]:
(venv) C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\import\05>cd ..
(venv) C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\import>python 05/main_01.py
Traceback (most recent call last):
File "05/main_01.py", line 8, in <module>
from module4 import f4
ModuleNotFoundError: No module named 'module4'
- рядок 2: під час виконання [main_01] ми вже не перебуваємо в папці [import/05], а в [import]. Однак ми написали:
sys.path.append(".")
sys.path.append("./dir1")
sys.path.append("./dir2")
Це додає до Python Path папки [import, import/dir1, import/dir2], що зовсім не те, чого ми хочемо. Зауважимо, що додавання до Python Path папок, яких не існує (import/dir1, import/dir2), не викликає помилок.
Ми просунулися вперед, але цього недостатньо. До Python Path потрібно додавати не відносні, а абсолютні шляхи.
Скрипт [main_02] є варіантом [main_01], який використовує файл конфігурації [config.json]:
{
"dependencies": [
"C:/Data/st-2020/dev/python/cours-2020/python3-flask-2020/import/05/dir1",
"C:/Data/st-2020/dev/python/cours-2020/python3-flask-2020/import/05/dir2"
]
}
Значенням ключа [dependencies] є список папок, які потрібно додати до Python Path. Зверніть увагу, що тут вказано абсолютні, а не відносні імена.
Скрипт [main_02] використовує файл [config.json] наступним чином:
import codecs
import json
import sys
# файл конфігурації
config_filename="C:/Data/st-2020/dev/python/cours-2020/python3-flask-2020/import/05/config.json"
# читання файлу конфігурації json
with codecs.open(config_filename, "r", "utf-8") as file:
config = json.load(file)
# зміна sys.path
for directory in config['dependencies']:
sys.path.append(directory)
# імпортуємо module4
from module4 import f4
# виконання f4
f4()
- рядок 6: зверніть увагу, що використано абсолютне ім’я конфігураційного файлу;
- рядки 8–9: файл конфігурації зчитується. На основі його вмісту створюється словник [config] (рядок 9);
- рядки 11–13: елементи масиву [config['dependencies']] додаються до Python Path. Зауважимо, що оскільки в [config.json] вказано абсолютні імена папок, до Python Path додаються саме абсолютні імена;
- рядок 16: імпортується файл [module4]. Його має бути знайдено, оскільки тепер файл [dir2] знаходиться в Python Path;
Виконання дає ті самі результати, що й для [main_02], за винятком того, що скрипт продовжує працювати, коли папкою виконання вже не є [import/05]:
(venv) C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\import>python 05/main_02.py
f3
f4
У рядку 1 каталог виконання — [import].
Ми просунулися вперед. Ми побачили:
- що нам потрібно самостійно побудувати Python Path;
- що туди потрібно вносити абсолютні імена всіх папок, що містять модулі, які імпортує додаток;
Проте вказувати абсолютні шляхи у скриптах — це не вихід. Як тільки проект переносять на інший сервер, він перестає працювати. Нам потрібно знайти інше рішення.
9.6. Скрипти [import_06]

Примітка: папки [06, dir1, dir2] було розміщено в папці [Sources Root] проекту PyCharm. Папки [dir1, dir2] ідентичні тим, що наведено в попередніх прикладах.
Файл [config.json] має такий вигляд:
{
"rootDir": "C:/Data/st-2020/dev/python/cours-2020/v-02/imports/06",
"relativeDependencies": [
"dir1",
"dir2"
],
"absoluteDependencies": [
]
}
Ми вводимо два типи шляхів:
- абсолютні шляхи, рядки 7–8;
- відносні шляхи, рядки 3–6. Вони відносяться до кореневого каталогу, вказаного в рядку 2. Таким чином, коли проект переміщується в інше місце, потрібно змінити лише цей рядок;
Скрипт [utils.py] використовує файл [config.json] і формує шлях Python:
# імпорт
import codecs
import json
import os
import sys
# конфігурація додатка
def config_app(config_filename: str) -> dict:
# config_filename: ім’я файлу конфігурації
# дозволяти передачу винятків
# обробка файлу конфігурації
with codecs.open(config_filename, "r", "utf-8") as file:
config = json.load(file)
# додавання залежностей до sys.path
rootDir = config['rootDir']
# додаємо відносні залежності проекту до syspath
for directory in config['relativeDependencies']:
# додаємо залежність на початок syspath
sys.path.insert(0, f"{rootDir}/{directory}")
# додаємо до syspath абсолютні залежності проекту
for directory in config['absoluteDependencies']:
# додаємо залежність на початок syspath
sys.path.insert(0, directory)
# створюється словник конфігурації
return config
# папку, з якої виконується скрипт
def get_scriptdir():
return os.path.dirname(os.path.abspath(__file__))
- рядок 8: функція [config_app] отримує як параметр ім’я конфігураційного файлу;
- рядки 12–14: файл конфігурації використовується для створення словника [config];
- рядок 20: [sys.path] — це список папок Python Path;
- рядки 17–20: відносні залежності з конфігураційного файлу додаються до Python Path. Вони додаються на початок масиву [sys.path], рядок 20. Адже коли Python шукає модуль, він послідовно обходить папки з [sys.path]. Однак у цьому документі модулі з однаковими іменами будуть розташовані в різних папках [sys.path]. Розмістивши залежності додатка на початку масиву [sys.path], ми гарантуємо, що вони будуть обшукані раніше, ніж інші папки [sys.path], які можуть містити модулі з однаковими іменами;
- рядки 21–24: абсолютні залежності конфігураційного файлу додаються до Python Path;
- рядок 26: повертається конфігурація додатка;
- рядки 29–30: функція [get_scriptdir] повертає абсолютний шлях до папки скрипта, що виконується (тобто того, в якому знаходиться виклик функції);
Головний скрипт [main] має такий вигляд:
# імпортування
import sys
from utils import config_app
def affiche_path(msg: str):
# повідомлення
print(f"{msg}------------------------------")
# sys.path
for path in sys.path:
print(path)
# main -------------
try:
# sys.path налаштовано
affiche_path("avant....")
config = config_app(f"{get_scriptdir()}/config.json")
affiche_path("après....")
# імпортуємо module4
from module4 import f4
# виконання f4
f4()
except BaseException as erreur:
print(f"L'erreur suivante s'est produite : {erreur}")
finally:
print("done")
- рядок 4: імпортується функція [config_app]. Слід зауважити, що оскільки [utils] та [main] знаходяться в одній папці, ця функція [import] працює завжди. Дійсно, папка головного скрипта автоматично додається до Python Path;
- рядки 7–12: функція [affiche_path] виводить список папок у Python Path;
- рядок 19: налаштовуємо додаток. Зверніть увагу, що до функції [config_app] передаємо абсолютний шлях до файлу конфігурації. Після цієї інструкції шлях Python Path було відновлено;
- рядок 22: імпортується [module4]. Завдяки відновленню Python Path цей модуль буде знайдено;
- рядок 24: виконується функція [f4];
У контексті PyCharm результати виконання такі:
C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\venv\Scripts\python.exe C:/Data/st-2020/dev/python/cours-2020/python3-flask-2020/import/06/main.py
avant....------------------------------
C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\import\06
C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020
C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\fonctions\shared
C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\impots\v01\shared
…
C:\Program Files\Python38\python38.zip
C:\Program Files\Python38\DLLs
C:\Program Files\Python38\lib
C:\Program Files\Python38
C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\venv
C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\venv\lib\site-packages
après....------------------------------
C:/Data/st-2020/dev/python/cours-2020/v-02/imports/06/dir2
C:/Data/st-2020/dev/python/cours-2020/v-02/imports/06/dir1
C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\import\06
C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020
C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\fonctions\shared
C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\impots\v01\shared
….
C:\Program Files\Python38\python38.zip
C:\Program Files\Python38\DLLs
C:\Program Files\Python38\lib
C:\Program Files\Python38
C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\venv
C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\venv\lib\site-packages
f3
f4
done
Process finished with exit code 0
Коментарі
- рядки 2–13: Python Path для PyCharm. У ньому містяться всі папки, додані до [Sources Root] цього проєкту;
- рядки 14–29: Python Path, сформований функцією [config_app]. У рядках 15–16 містяться дві залежності, які ми додали;
- рядки 22–27: системні папки інтерпретатора Python, який виконав скрипт;
- рядки 28–29: виконання відбувається нормально;
Тепер перейдемо до контексту, який до цього моменту викликав помилку виконання:
- запускаємо термінал Python;
- переходимо в папку, відмінну від тієї, що містить виконуваний скрипт;
(venv) C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\import>python 06/main.py
avant....------------------------------
C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\import\06
C:\Program Files\Python38\python38.zip
C:\Program Files\Python38\DLLs
C:\Program Files\Python38\lib
C:\Program Files\Python38
C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\venv
C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\venv\lib\site-packages
après....------------------------------
C:/Data/st-2020/dev/python/cours-2020/v-02/imports/06/dir2
C:/Data/st-2020/dev/python/cours-2020/v-02/imports/06/dir1
C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\import\06
C:\Program Files\Python38\python38.zip
C:\Program Files\Python38\DLLs
C:\Program Files\Python38\lib
C:\Program Files\Python38
C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\venv
C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\venv\lib\site-packages
f3
f4
done
Цього разу все гаразд (рядки 20–21). Зауважимо, що [sys.path] не містить тих самих папок, що й під час виконання під PyCharm.
9.7. Скрипти [import_07]
Ми вдосконалюємо попереднє рішення двома способами:
- замінюємо файл конфігурації [config.json] на скрипт [config.py]. Справа в тому, що файл jSON має суттєву проблему: його неможливо коментувати. Словник [config.json] можна замінити на словник Python, який має ту перевагу, що його можна коментувати;
- ми використовуємо модуль, доступний для всіх Python-проектів на цій машині;
9.7.1. Встановлення модуля, доступного на всьому комп’ютері

Вище ми створюємо папку [packages/myutils] у проєкті PyCharm (назви не мають значення).
Скрипт [myutils.py] має такий вигляд:
# імпорт
import sys
import os
def set_syspath(absolute_dependencies: list):
# absolute_dependencies: список абсолютних імен папок
# додаємо до syspath абсолютні залежності проекту
for directory in absolute_dependencies:
# перевіряється наявність папки
existe = os.path.exists(directory) and os.path.isdir(directory)
if not existe:
# генерується виняток
raise BaseException(f"[set_syspath] le dossier du Python Path [{directory}] n'existe pas")
else:
# додаємо папку на початок syspath
sys.path.insert(0, directory)
- рядки 6–18: функція [set_syspath] створює Python Path із списком папок, які передаються їй як параметр;
- рядки 12–15: перевіряється, чи існує папка, яку потрібно додати до Python Path;
Скрипт [__init.py__] (дві риски перед і після імені; це обов’язкова умова) має такий вигляд:
from .myutils import set_syspath
Імпортуємо функцію [set_syspath] зі скрипта [myutils]. Позначення [.myutils] вказує на шлях [./myutils], тобто скрипт [myutils], що знаходиться в тій самій папці, що й [__init.py]. Можна було б використати позначення [myutils]. Однак ми створимо модуль [myutils] з областю дії на рівні машини. Тому позначення [from myutils import set_syspath] стало б неоднозначним. Чи йдеться про імпорт скрипта [myutils] із поточної папки, чи скрипта [myutils], що має область дії на рівні машини? Позначення [.myutils] усуває цю неоднозначність.
Скрипт [setup.py] (тут також ім’я є фіксованим) має такий вигляд:
from setuptools import setup
setup(name='myutils',
version='0.1',
description='Utilitaire fixant le Python Path',
url='#',
author='st',
author_email='st@gmail.com',
license='MIT',
packages=['myutils'],
zip_safe=False)
У цьому скрипті описується модуль, який ми збираємося створити. У даному випадку ми створимо його локально. Але той самий процес використовується для створення офіційно розповсюджуваного модуля (див. |pypi|). Важливими моментами тут є наступні:
- рядок 3: назва створюваного модуля;
- рядок 4: версія модуля;
- рядок 5: його опис;
- рядки 7–8: автор модуля;
Щоб встановити цей модуль із охопленням на рівні машини, слід виконати такі дії:

Потім у терміналі Python вводять таку команду: [pip install .]:
(venv) C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\packages>pip install .
Processing c:\data\st-2020\dev\python\cours-2020\python3-flask-2020\packages
Using legacy setup.py install for myutils, since package 'wheel' is not installed.
Installing collected packages: myutils
Attempting uninstall: myutils
Found existing installation: myutils 0.1
Uninstalling myutils-0.1:
Successfully uninstalled myutils-0.1
Running setup.py install for myutils ... done
Successfully installed myutils-0.1
Відтепер будь-який скрипт машини може імпортувати модуль [myutils], навіть якщо він не входить до коду проєкту.
9.7.2. Скрипт [config.py]

Скрипт [config.py] забезпечує налаштування додатка:
def configure():
import os
# абсолютний шлях до папки конфігураційного скрипта
script_dir = os.path.dirname(os.path.abspath(__file__))
# абсолютні шляхи до папок, які потрібно додати до syspath
absolute_dependencies = [
# локальні папки
f"{script_dir}/dir1",
f"{script_dir}/dir2",
]
# оновлення syspath
from myutils import set_syspath
set_syspath(absolute_dependencies)
# повертаємо конфігурацію
return {}
- рядок 1: функція [configure] забезпечує налаштування додатка;
- рядки 7–10: словник, який раніше містився у [config.json];
- рядки 9–10: оскільки ми перебуваємо у скрипті, ми можемо безпосередньо використовувати абсолютні імена папок [dir1, dir2];
- рядки 12–14: використовуємо функцію [set_syspath] з модуля [myutils], який ми щойно створили, щоб визначити Python Path конфігурації;
- рядок 20: повертаємо словник конфігурації додатка. Тут він порожній;
9.7.3. Скрипт [main.py]
Головний скрипт [main] має такий вигляд:
# налаштовуємо додаток
import config
config = config.configure()
# syspath налаштовано — можна виконувати імпорт
from module4 import f4
# main -------------
try:
f4()
except BaseException as erreur:
print(f"L'erreur suivante s'est produite : {erreur}")
finally:
print("done")
- рядки 2–4: налаштовуємо додаток за допомогою модуля [config.py]. Доступ до нього є, оскільки він знаходиться в тій самій папці, що й головний скрипт. А папка головного скрипта завжди входить до Python Path;
- коли доходимо до рядка 6, Python Path вже сформовано з урахуванням папки модуля [module4]. Отже, його можна імпортувати в рядку 7;
- рядки 10–15: залишається лише виконати функцію [f4];
Результати виконання в PyCharm такі:
У терміналі Python, розташованому поза папкою головного скрипта, результати такі:
Відтепер ми завжди будемо діяти таким самим чином для налаштування додатка:
- наявність скрипта [config.py] у папці головного скрипта. Цей скрипт містить функцію [configure], яка має два завдання:
- сформувати Python Path для додатка. Для цього [config.py] визначає всі папки, що містять модулі, які використовує додаток, і формує Python Path із їхніми абсолютними іменами;
- сформувати словник [config] конфігурації додатка;
Ми застосовуємо цю схему до другої версії практичного завдання. Адже, як ми пам’ятаємо, версія 1 працювала в середовищі PyCharm, але не в терміналі Python. Проблема полягала в Python Path.