קובץ אחד הוא מודול
ברגע שקוד ה-Python שלכם גדל מעבר לסקריפט יחיד, תרצו לפצל אותו לכמה קבצים. מערכת המודולים של Python פשוטה: כל קובץ .py הוא אוטומטית מודול שאפשר לייבא לפי השם.
נניח שיש לכם קובץ util.py:
# util.py
def greet(name):
return f"Hello, {name}"
PI = 3.14159
מקובץ אחר באותה תיקייה, main.py, אפשר להשתמש בו:
# main.py
import util
print(util.greet("Ada"))
print(util.PI)
הריצו python3 main.py, ו-Python תמצא את util.py, תריץ אותו פעם אחת, ותחשוף את כל מה שמוגדר ברמה העליונה (פונקציות, משתנים, מחלקות) כ-attributes של המודול util.
שלוש צורות הייבוא
ייבוא של המודול כולו. ניגשים לדברים שבפנים דרך שם המודול:
ייבוא של שמות מסוימים. הם זמינים ישירות:
ייבוא עם כינוי. שימושי כששם המודול ארוך או כששני מודולים חולקים שם:
import numpy as np
import pandas as pd
# עכשיו משתמשים ב-np.array(...), pd.DataFrame(...), וכו'.
יש צורה רביעית, from math import *, שמכניסה הכול למרחב השמות שלכם. הימנעו ממנה מחוץ לניסויים ב-REPL: היא לא מאפשרת לדעת מאיפה הגיע שם, והיא יוצרת התנגשויות שמות שקטות.
מתי ייבוא רץ
Python מריצה את הקוד ברמה העליונה של מודול מיובא פעם אחת, בפעם הראשונה שהוא מיובא בתוכנית נתונה. ייבואים נוספים של אותו מודול מחזירים את הגרסה שכבר נטענה. כך שזה:
# setup.py
print("setup module loading...")
VALUE = 42
# main.py
import setup
import setup # מיובא פעמיים, אבל "loading" מודפס רק פעם אחת
print(setup.VALUE)
מדפיס את "setup module loading..." רק פעם אחת. זה חשוב: אם שמים תופעות לוואי (כמו פתיחת קובץ או הדפסה) ברמה העליונה של המודול, הן קורות בזמן הייבוא, ובדרך כלל זה לא מה שרוצים. שימו אותן בתוך פונקציות.
הספרייה הסטנדרטית
Python מגיעה עם ספרייה סטנדרטית גדולה של מודולים. כבר ראיתם כמה. הנה כמה שתשתמשו בהם כל הזמן:
math: sqrt, sin, log, וקבועים כמוpiו-e.random: מספרים אקראיים, בחירות וערבוב.datetime: תאריכים ושעות.json: קריאה וכתיבה של JSON.os,os.path: נתיבים ופעולות במערכת הקבצים.pathlib: טיפול מודרני בנתיבים, לעיתים קרובות נוח יותר מ-os.path.re: ביטויים רגולריים.collections: סוגי אוספים מיוחדים (Counter,defaultdict,dequeועוד).itertools,functools: כלי עזר ל-iterators ולפונקציות.csv: קריאה וכתיבה של קובצי CSV.
הספרייה הסטנדרטית כבר מותקנת, אין מה להתקין עם pip.
חבילות צד שלישי ו-pip
לכל מה שהספרייה הסטנדרטית לא מכסה, ה-Python Package Index (PyPI) מארח מאות אלפי חבילות. מתקינים אותן עם pip:
pip install requests
pip install pandas
pip install --upgrade requests
pip uninstall requests
אחרי ההתקנה מייבאים אותן כמו כל דבר אחר:
import requests
response = requests.get("https://api.example.com/data")
print(response.status_code)
כמה טיפים לניהול שפוי של זה:
השתמשו בסביבות וירטואליות
התקנה של הכול באופן גלובלי מובילה לכאב ראש. פרויקטים שונים צריכים גרסאות שונות, חלק מהחבילות תלויות בגרסאות Python מסוימות, ובחלק מהמערכות התקנות גלובליות דורשות הרשאות מנהל. סביבה וירטואלית היא התקנת Python מבודדת לפרויקט אחד בלבד:
python3 -m venv .venv
source .venv/bin/activate # macOS/Linux
.venv\Scripts\activate # Windows
pip install requests
כל עוד ה-venv פעיל, pip מתקין לתוך תיקיית הפרויקט ולא למערכת שלכם. בטלו את ההפעלה עם deactivate כשסיימתם.
נעצו את התלויות שלכם
שמרו את רשימת החבילות המותקנות כדי שאחרים (כולל אתם בעתיד) יוכלו ליצור מחדש את אותה סביבה:
pip freeze > requirements.txt
ואחר כך:
pip install -r requirements.txt
כלים כמו Poetry, pipenv ו-uv מטפלים בזה בצורה נוחה יותר, אבל תהליך העבודה הפשוט של pip + requirements.txt עדיין מצוין ללמידה.
כתיבת מודולים משלכם
ברגע שיש לכם פונקציות שאתם רוצים להשתמש בהן בכמה קבצים, שימו אותן במודול משלהן. מוסכמות שמות:
- שמות קבצים צריכים להיות
lower_snake_case.py. - גם פונקציות ומשתנים ברמת המודול כתובים ב-
lower_snake_case. - מחלקות כתובות ב-
PascalCase.
# shopping.py
PRICES = {"apple": 0.50, "bread": 2.00}
def total(items):
return sum(PRICES[item] for item in items)
# main.py
from shopping import total, PRICES
print(total(["apple", "bread"]))
print(PRICES)
אם שני קבצים באותה תיקייה מייבאים זה את זה, אתם עלולים ליצור בטעות ייבוא מעגלי. הפתרון המקובל הוא להעביר את הקוד המשותף לקובץ שלישי ששניהם מייבאים.
חבילות: תיקיות של מודולים
כשיש לכם יותר מקומץ מודולים, קבצו אותם ל-חבילה (package): תיקייה שיש בה קובץ __init__.py:
myproject/
├── main.py
└── utils/
├── __init__.py
├── text.py
└── numbers.py
ואז:
from utils.text import slugify
from utils import numbers
print(slugify("Hello, World"))
print(numbers.mean([1, 2, 3]))
הקובץ __init__.py יכול להיות ריק: הנוכחות שלו היא מה שהופך את utils לחבילה. Python מודרנית תומכת גם ב"namespace packages" בלי __init__.py, אבל בהתחלה הגרסה המפורשת ברורה יותר.
רשימת בדיקה קטנה כשייבוא נשבר
- "ModuleNotFoundError: No module named X". או שהחבילה לא מותקנת, או שאתם מריצים Python ממפרש אחר מזה שעליו הרצתם
pip install. ב-venv, ודאו שה-venv מופעל. - "ImportError: cannot import name Y from X". המודול קיים, אבל השם שביקשתם לא נמצא בו. בדקו שגיאות הקלדה והסתכלו על התוכן בפועל של המודול.
- "Circular import". שני מודולים מייבאים זה את זה. העבירו את הקוד המשותף למודול שלישי.
הצעד הבא: התקנת חבילות צד שלישי
המודולים שלכם יביאו אתכם רחוק, אבל רוב הפרויקטים האמיתיים משתמשים גם בספריות מ-PyPI: requests, pandas, מסגרת בדיקות. העמוד הבא מסביר את pip, איך להתקין חבילות בצורה נקייה, ואיך לתעד במה הפרויקט שלכם תלוי.
שאלות נפוצות
מה זה מודול ב-Python?
מודול הוא כל קובץ .py. קובצי Python הופכים אוטומטית למודולים, ומייבאים אותם לפי השם (בלי ה-.py). הספרייה הסטנדרטית היא אוסף גדול של מודולים מובנים כמו math, json ו-datetime שמגיעים עם כל התקנה של Python.
מה ההבדל בין import X ל-from X import Y?
import X מייבא את כל המודול, וניגשים לדברים שבתוכו עם X.something. from X import Y מכניס רק את Y למרחב השמות שלכם, כך שאפשר להשתמש בו ישירות כ-Y. הצורה הראשונה בטוחה יותר (אין התנגשויות שמות), והשנייה קומפקטית יותר.
איך מתקינים חבילת Python?
הריצו pip install package_name בטרמינל. pip הוא מנהל החבילות של Python ומגיע עם ההתקנות המודרניות. כדי לבודד פרויקטים, צרו קודם סביבה וירטואלית, כך שחבילות מותקנות לא יזלגו בין פרויקטים.