ניהול חבילות בפייתון עם פואטרי

מנהל הסביבה המוביל של פייתון שכדאי להכיר ולעבוד איתו.

לפני קריאת פוסט זה מוטב לעבור על הפוסטים הקודמים בסדרה – הפוסט על pyenv, שעוזר לנו לנהל את גרסת הפייתון במחשב עצמו (3.11? 3.9? 3.7? אפשר לנהל, לעבור ולשדרג בקלות עם pyenv). בפוסט ההמשך דיברנו על pip + venv, שזה מנהל החבילות הראשון של פייתון ובפוסט הקודם דיברנו על pipenv, שזה מנהל חבילות מודרני. בפוסט הזה אנחנו נדבר על Poetry, שזה מנהל החבילות הפופולרי ביותר של פייתון שדומה ל pipenv אבל שונה ממנו בכמה אספקטים חשובים:

  • פיצ׳רים ונוחות שימוש – קובץ הקונפיגורציה והניהול של פואטרי הרבה הרבה יותר קלים ופשוטים לשימוש מצד אחד וגם מכילים הרבה יותר פונקציונליות מהצד השני.
  • טיפול ב depenency hell שאיזכרתי במאמר הקודם. למשל שיש חבילה A שצריכה את C מגרסה 1 וחבילה B שצריכה את C מגרסה 2. במה לבחור? אז בפואטרי יש את libpoetry שעושה עבודה יותר טובה ביישוב סתירות כאלו מ-pipenv.
  • ביצועים ומהירות.

ובגדול, הקונספט של פואטרי לא שונה מהותית מpipenv והוא קל לשימוש. מכירים pipenv? תוך דקות תוכלו להסתדר עם פואטרי. באופן אישי? אני משתמש בו.

התקנה

הדוקומנטציה של פואטרי ממש מוצלחת! יש הוראות להתקנה פשוטה וקלה גם בחלונות וגם בסביבות אחרות. במק זה ממש פשוט! מקלידים:

curl -sSL https://install.python-poetry.org | python3 -

ואז מוודאים שיש הפניה ל-PATH המתאים ב zshrc שלכם (אם אתם משתמשים ב-zsh ואתם משתמשים בו). אם זה נשמע לכם כמו סינית – אם אתם צריכים, ה-install script יגיד לכם מה לעשות:

Add `export PATH="/Users/barzik/.local/bin:$PATH"` to your shell configuration file.

כדי לבדוק שהכל עובד, אנו נקליד:

poetry --version

אם מקבלים תוצאה? הכל טוב ואפשר להתחיל לעבוד. אם לא – אז שימו לב:

  1. לוודא שבאמת ה-PATH שלכם מעודכן.
  2. לעשות omz reload אחרי העדכון (אם אתם משתמשים ב-OMZ) או לסגור ולפתוח את הטאב של הקונסולה.

עבודה ראשונית עם pyproject.toml

פואטרי עובד עם קובץ הגדרה בפורמט שנקרא toml. זה פורמט די מוכר שמשתמשים בו בלא מעט מקומות ומגדיר את הפרויקט – מי מנהל אותו, מה התלויות שלו, מה גרסת הפייתון שלו וכו׳ וכו׳. אפשר ליצור את הקובץ הזה, שהוא קובץ טקסטואלי עם כל עורך קוד או להשתמש בפקודה poetry init על מנת ליצור קובץ כזה – בפרויקט קיים או פרויקט חדש. הכלי שרץ ב poetry init ישאל אותנו כל מיני שאלות ואז יצור pyproject.toml. מתכנתי Node.js? זה בדיוק כמו npm init ו-package.json.

הנה למשל קובץ לדוגמה. אין פה מדע טילים ואני חושב שהוא די ברור:

[tool.poetry]
name = "python-poetry-demo"
version = "0.1.0"
description = "This is a demo project"
authors = ["Ran Bar-Zik <[email protected]>"]
license = "BSD"
readme = "README.md"
packages = [{include = "python_poetry_demo"}]

[tool.poetry.dependencies]
python = "^3.9"


[build-system]
requires = ["poetry-core"]
build-backend = "poetry.core.masonry.api"

מה שמעניין אותנו הוא ה-tool.poetry.dependencies. שהוא מכיל את החבילות התלויות והגרסאות. בפרויקט חדש יהיה לנו את פייתון בלבד (שזה די ברור, לא?) ואת הגרסה. למי שלא עבר על המאמר הקודם – הגרסאות פה ובכל מקום אחר הן לפי Semantic Versions והסימנים שלהן. אם יש רק מספר, זה אומר את הגרסה הזו בלבד.
גרסה עם כובע ^ זה אומר מיינור ומייג׳ור. למשל 3.9 עם ^ זה אומר 3.9 ומעלה אבל לא 4 (אין עדיין 4 בפייתון אבל תזרמו איתי). גרסה עם ~ זה אומר רק פאצ׳ים. למשל 3.9~ זה אומר 3.9 ומעלה – כלומר 3.9.0, 3.9.10 או 3.9.35 אבל לא 3.10 או 3.12 ובטח שלא 4. מי שצריך עוד הסבר – יש את האתר של semver שמסביר.

בואו ונתקין חבילת תוכנה ראשונה! נתקין את חבילת requests! זה פשוט. מקלידים poetry add requests. אחרי ההתקנה, אנו נראה שהיא התווספה ל-pyproject.toml:

[tool.poetry.dependencies]
python = "^3.9"
requests = "^2.28.2"

כמובן של-requests יש את התלויות שלה – הכל יופיע בקובץ poetry.lock שמכיל את הגרסאות המדויקות של כל החבילות במועד ההתקנה. בכל התקנה של חבילה חדשה, קובץ poetry.lock יתעדכן. אם יש התנגשות בין גרסאות – אז Poetry ינסה לפשר בינהם עם אלגוריתם מחוכם יותר.
הקובץ poetry.lock ו-pyproject.toml נכנסים לגיט.

אם יש קובץ poetry.lock ואנו מקלידים poetry install – תבוצע התקנה ישירות לפי הגרסאות שיש ב poetry.lock – שימו לב שזה שונה פה מ-pipenv.

כדי לעדכן את poetry.lock אנו צריכים לעשות poetry update ואז poetry.lock יתעדכן לפי הגרסאות שהגדרנו ב pyproject.toml.

הסרה של חבילות תוכנה נעשית עם

poetry remove

ושם החבילה.

הרצה

החבילות וה-bin של גרסת פייתון הרלוונטית מותקנות ב-״סביבה וירטואלית״ (אין קשר למחשב וירטואלי, אני יודע שזה מבלבל) כמובן. בדיוק כמו pipenv ו pip + venv. איפה מיקום תיקית ה-venv.? אני יכול להקליד:

poetry show -v

ולראות היכן הסביבה מותקנת. אם אני לא עושה שום דבר, הסביבה מותקנת בתיקיה גלובלית ב-cache:

poetry show -v                                                                             ok
Using virtualenv: /Users/barzik/Library/Caches/pypoetry/virtualenvs/python-poetry-demo-T5PUDhem-py3.9

זו התנהגות שיש גם ב-venv. אני פחות מתלהב מזה ואוהב שהסביבה הוירטואלית נמצאת מתחת לפרויקט. על מנת לשנות את זה אני משתמש בקונפיגורציה של פואטרי שהיא ממש מוצלחת. אני מקליד את השורה:

poetry config virtualenvs.create true

ואז מפעיל מחדש את הטרמינל. מהנקודה הזו כל פרויקט שמותקן מחדש, יצור את תיקית ה-venv בפרויקט עצמו.

לא משנה איפה קבצי הספריה הוירטואלית מופעלים. על מנת להשתמש בהם, אני משתמש ב-shell. אני מקליד poetry shell בקונסולה ואז נכנס ל״קונטקסט״ של הסביבה הוירטואלית ויכול להפעיל את הפרויקט ותהיה לו גישה את המודולים והוא ירוץ כמובן בסביבת ההרצה של גרסת פייתון שהגדרנו לו. בדרך כלל תהיה אינדיקציה גרפית כלשהי בקונסולה לכך. אני משתמש ב-powerlevel10k אז האינדיקציה תהיה python-poetry-demo py מצד ימין. אם זה zsh רגיל אז יהיו סוגריים מסביב לטרמינל.

אינדיקציה של ה-CLI מצד ימין:
ok | python-poetry-demo py

עבודה עם קבוצות/ מוד פיתוח

בניגוד ל-pipenv שמאפשר לי רק dev ופרודקשן, בפואטרי יש לי יכולת ליצור קבוצות של תלויות בהתאם לסביבה. למשל אם אני רוצה תלויות שעובדות רק בסביבת פיתוח. אני יוצר קבוצה שנקראת dev. אם אני רוצה, מכל מיני סיבות, ליצור תלויות שעובדות רק בסביבת stage, אני יכול ליצור קבוצה שנקראת stage.

בואו ונדגים. נניח שאני רוצה להתקין רק חבילות שצריך במהלך פיתוח. אני מתקין כרגיל אבל באמצעות הוספת הפקודה –group dev:

poetry add --group dev pylint

אני אראה שיש לי פתאום קבוצה חדשה בקובץ ה-pyproject.toml

[tool.poetry]
name = "python-poetry-demo"
version = "0.1.0"
description = "This is a demo project"
authors = ["Ran Bar-Zik <[email protected]>"]
license = "BSD"
readme = "README.md"
packages = [{include = "python_poetry_demo"}]

[tool.poetry.dependencies]
python = "^3.9"
requests = "^2.28.2"


[tool.poetry.group.dev.dependencies]
pytest = "^7.2.2"
pylint = "^2.17.1"

[build-system]
requires = ["poetry-core"]
build-backend = "poetry.core.masonry.api"

אני חושב שהפוסט הזה התארך ויש בהחלט מקום לפוסט המשך שיגיע על יכולות נוספות של פואטרי ועבודה מתקדמת איתו. אבל אם אתם משתמשים ב-pipenv או שיש לכם פרויקט חדש, בהחלט כדאי לקחת את פואטרי לסיבוב ולהתנסות איתו. העבודה דומה, כפי שאמרנו ואפשר גם לראות, לpipenv. יש יכולות חדשות, הביצועים טובים בהרבה ובכלל הוא מרגיש יותר אינטואטיבי. כמתכנת שמכיר היטב גם ג׳אווהסקריפט ו-Node.js, העבודה איתו הרבה יותר אינטואיטיבית.

פוסטים נוספים שכדאי לקרוא

פתרונות ומאמרים על פיתוח אינטרנט

המנעו מהעלאת source control לשרת פומבי

לא תאמינו כמה אתרים מעלים את ה-source control שלהם לשרת. ככה תמצאו אותם וגם הסבר למה זה רעיון רע.

בינה מלאכותית

Safeguards על מודל שפה גדול (LLM)

פוסט בשילוב עם פודקאסט וסרטון על ההגנות שאפשר להציב על LLM בסביבת פרודקשן

בינה מלאכותית

להריץ ממשק של open-webui על הרספברי פיי

להפעיל ממשק של צ׳אט ג׳יפיטי שאפשר לגשת אליו מכל מחשב ברשת הביתית על רספברי פיי עם מודל בשם tinydolphin שרץ על רספברי פיי.

גלילה לראש העמוד