מודולים בפייתון – חלק ב

בפוסט מודולים בפייתון – חלק א, פגשנו את הפקודה import המאפשרת לייבא מודול אל המודול הנוכחי (או אל ה – interpreter).python modules

הרצת מודול כסקריפט

לעיתים רוצים "להריץ" מודול מסויים בנפרד ממודולים אחרים.
נניח כי כתבנו שני מודולים: AA ו BB.
הנה BB:

def get_name():
    fname = input('Enter your first name, please:')
    lname = input('Enter your last name, please:')
    return (fname, lname)

והנה AA:

import BB

BB.get_name()


והנה הבעייה:
לעיתים נרצה "להריץ" את מודול BB ללא AA, למשל כדי לבדוק ש – BB פועל כשורה.
מה שבאמת נרצה לעשות הוא, לקרוא לפונקציה get_name ישירות מתוך מודול BB (כדי לבדוק אותה).
היינו רוצים להשאיר שם (בתוך BB) את קוד הבדיקה, אבל שלא ייתבצע אם מפעילים את BB באמצעות import מתוך AA.
כלומר – ברצוננו לכתוב קוד נוסף בתוך BB, שייתבצע רק אם BB הוא "המודול הראשי" בתוכנית.
אפשר לעשות זאת.
המשתנה המובנה בפייתון __name__ (כלומר שני קווים תחתונים לפני ואחרי) יאפשר לנו לעשות זאת.
כתבתי את הפקודה הבאה בתוך קובץ פייתון בשם x.py:

print(__name__)

אריץ את תוכן הקובץ בשתי צורות:

yuval> ls -l x.py 
-rw-rw-r-- 1 yuval yuval 15 Oct 23 18:23 x.py
yuval> python3 x.py 
__main__
yuval> 
yuval> python3
Python 3.8.5 (default, Sep  9 2020, 11:29:34) 
[GCC 9.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import x
x
>>> 

כלומר, ערך המשתנה הוא  "__main__"  כאשר המודול מורץ כמודול ראשי (מודגש בכחול), אבל ערכו הוא שם המודול ("x" במקרה זה) כאשר הוא מיובא (מודגש בכתום).
נוכל לנצל זאת, ולכתוב קוד שקורא לפונקציה בתוך BB, קוד שלא ייתבצע אם מייבאים את BB מתוך AA:

def get_name():
    fname = input('Enter your first name, please:')
    lname = input('Enter your last name, please:')
    return (fname, lname)

if __name__ == '__main__':  # so if BB is the main module
    names = get_name()
    print(f'first name is: {names[0]}, last name is {names[1]}.')

המודולים המובנים (standard modules)

הסיפריה הסטנדארטית של פייתון היא אוסף של מודולים מובנים בפייתון.
היא כוללת מודולים רבים בנושאים שונים המובנים ישר בתוך ה – interpreter, חלקם תלויים בסביבת הריצה. המודולי winreg למשל, מספק גישה ל registry של Windows, ונמצא רק בגירסת פייתון ל Windows.
את המודול sys נזכיר בחלק הבא.

איפה המודול

לעיתים המודול נמצא בתיקיות (directories) אחרות, ופייתון צריך לדעת היכן לחפש.
אפשר לדעת את רשימת התיקיות בהן פייתון מחפש בדרך הבאה:

>>> import sys
>>> sys.path
['', '/usr/local/lib/python38.zip', '/usr/local/lib/python3.8', '/usr/local/lib/python3.8/lib-dynload', '/home/yuval/.local/lib/python3.8/site-packages', '/usr/local/lib/python3.8/site-packages']
>>> 

במקרה זה הרשימה לא כוללת את התיקייה בא נמצא הקובץ אותו ברצוני לייבא:

>>> import AA
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/yuval/Documents/languages/python/progs/module_import/AA.py", line 1, in <module>
    import module_import.BB
ModuleNotFoundError: No module named 'module_import'
>>> 

רשימת התיקיות מאותחלת מתוך משתנה סביבה הנקרא PYTHONPATH.
גם כאשר מגדירים תיקייה ב- PyCharm  כ – Sources Root, התיקייה נוספת לרשימת החיפוש.

הפונקציה ()dir

הפונקציה ()dir מציגה את השמות אותם המודולים מגדירים.
עם פרמטר (שם של מודול), הפונקציה מציגה את השמות של אותו מודול.
ללא פרמטר – מציגה את השמות שהוגדרו לוקאלית:

>>> dir()
['__annotations__', '__builtins__', '__doc__', '__loader__', '__name__', '__package__', '__spec__', 'sys']
>>> 
>>> dir(sys)
['__breakpointhook__', '__displayhook__', '__doc__', '__excepthook__', '__interactivehook__', '__loader__', '__name__', '__package__', '__spec__', '__stderr__', '__stdin__', '__stdout__', '__unraisablehook__', '_base_executable', '_clear_type_cache', '_current_frames', '_debugmallocstats', '_framework', '_getframe', '_git', '_home', '_xoptions', 'abiflags', 'addaudithook', 'api_version', 'argv', 'audit', 'base_exec_prefix', 'base_prefix', 'breakpointhook', 'builtin_module_names', 'byteorder', 'call_tracing', 'callstats', 'copyright', 'displayhook', 'dont_write_bytecode', 'exc_info', 'excepthook', 'exec_prefix', 'executable', 'exit', 'flags', 'float_info', 'float_repr_style', 'get_asyncgen_hooks', 'get_coroutine_origin_tracking_depth', 'getallocatedblocks', 'getcheckinterval', 'getdefaultencoding', 'getdlopenflags', 'getfilesystemencodeerrors', 'getfilesystemencoding', 'getprofile', 'getrecursionlimit', 'getrefcount', 'getsizeof', 'getswitchinterval', 'gettrace', 'hash_info', 'hexversion', 'implementation', 'int_info', 'intern', 'is_finalizing', 'maxsize', 'maxunicode', 'meta_path', 'modules', 'path', 'path_hooks', 'path_importer_cache', 'platform', 'prefix', 'ps1', 'ps2', 'pycache_prefix', 'set_asyncgen_hooks', 'set_coroutine_origin_tracking_depth', 'setcheckinterval', 'setdlopenflags', 'setprofile', 'setrecursionlimit', 'setswitchinterval', 'settrace', 'stderr', 'stdin', 'stdout', 'thread_info', 'unraisablehook', 'version', 'version_info', 'warnoptions']
>>> 

בחלק הבא נשלים את נושא המודולים, ונציג packages בפייתון.


כתיבת תגובה

האימייל לא יוצג באתר. שדות החובה מסומנים *