පයිතන් මොඩියුල සහ පැකේජ | Advanced Python Modules & Packages SC Guide

ආයුබෝවන්, අපේ කට්ටිය!
ඔන්න අදත් සුපිරි කතාවක් අරන් ආවා, විශේෂයෙන්ම Python කරන අයට. පොඩි පොඩි script ලියනකොට අවුලක් නැති වුණාට, ලොකු project එකක් කරන්න ගියාම, මේ code ටික හරියට manage කරගන්න එක ලොකු ගැටලුවක් වෙනවා. එතකොට තමයි අපේ Modules සහ Packages කියන වීරයෝ දෙන්නා අපේ ගලවාගැනීමට එන්නේ. හරි, අද අපි මේගොල්ලන්ගේ Advanced පැත්තට පොඩ්ඩක් ගිහින් බලමු, විශේෂයෙන්ම __name__ == "__main__"
කියන අමුතු කතාවයි, Package structure එකයි, ඒ වගේම tricky වෙන්න පුළුවන් Relative imports ගැනයි. අවසානයේදී මේ හැමදේම එකට එකතු කරලා, පොඩි project එකක් organize කරලා බලමු!
__name__ == "__main__"
– මොකක්ද මේ කතාව?
හරි, මුලින්ම මේ __name__ == "__main__"
කියන එකෙන් පටන් ගමු. Python වල script එකක් run කරනකොට, ඒ script එකට __name__
කියලා විශේෂ variable එකක් automatically ලැබෙනවා. මේකෙන් වෙන්නේ, අපි මේ script එක run කරන්නේ direct ද, නැත්නම් වෙන script එකකින් import කරලා ද කියලා දැනගන්න පුළුවන් වෙන එකයි.
__name__
කියන්නේ මොකක්ද?
Python වල හැම Module එකකටම (.py
file එකකට) __name__
කියලා built-in attribute එකක් තියෙනවා. මේක String එකක්.
අපි file එකක් direct run කරනකොට (e.g., python my_script.py
) __name__
කියන එකේ value එක "__main__"
වෙනවා.
ඒත්, අපි මේ file එක වෙන file එකකින් import කරනකොට (e.g., import my_script
), __name__
කියන එකේ value එක වෙන්නේ ඒ Module එකේ නම (file name එක, .py
නැතුව) (e.g., "my_script"
).
ප්රායෝගික උදාහරණයක්:
හිතන්න අපිට greeting.py
කියලා file එකක් තියෙනවා:
# greeting.py
def say_hello(name):
return f"ආයුබෝවන්, {name}!"
def say_goodbye(name):
return f"ගිහින් එන්නම්, {name}!"
if __name__ == "__main__":
# මේ code එක run වෙන්නේ greeting.py direct run කලොත් විතරයි
print("Greeting module එක direct run කරනවා.")
print(say_hello("අපේ යාළුවා"))
print(say_goodbye("සමනලී"))
else:
# මේ code එක run වෙන්නේ greeting.py වෙන Module එකකින් import කලොත් විතරයි
print("Greeting module එක import කරනවා.")
දැන් අපි මේක execute කරලා බලමු:
වෙන file එකකින් import කරනකොට: හිතන්න අපිට main_app.py
කියලා file එකක් තියෙනවා:
# main_app.py
import greeting
print("Main application එකෙන් කතා කරන්නේ.")
print(greeting.say_hello("කමල්"))
දැන් අපි මේ main_app.py
එක run කරමු: python main_app.py
Greeting module එක import කරනවා.
Main application එකෙන් කතා කරන්නේ.
ආයුබෝවන්, කමල්!
මෙතනදී, greeting.py
file එක main_app.py
එකට import වුණා විතරයි. ඒ නිසා, greeting.py
ඇතුලේ __name__
එක "greeting"
වුණා. ඒ නිසා, else
block එක ඇතුලේ තියෙන code ටික run වුණා මිසක්, if __name__ == "__main__":
block එක ඇතුලේ තියෙන code ටික run වුණේ නෑ.
Directly run කරනකොට: python greeting.py
Greeting module එක direct run කරනවා.
ආයුබෝවන්, අපේ යාළුවා!
ගිහින් එන්නම්, සමනලී!
මෙතනදී, __name__
එක "__main__"
වුණ නිසා, if
block එක ඇතුලේ තියෙන code ටික run වුණා.
ඉතින්, if __name__ == "__main__":
කියන block එක පාවිච්චි කරන්නේ, Module එකක් වෙන Module එකකට import කරනකොට run වෙන්න ඕනේ නැති, ඒ Module එක direct run කරනකොට විතරක් run වෙන්න ඕනේ code ටික ලියන්නයි. Test code, Command-line argument parsing, හෝ Module එකටම අදාළ initialization වගේ දේවල් මේ block එක ඇතුලේ ලිවීම හොඳ practice එකක්.
පැකේජ වල Structure එක සහ __init__.py
ගේ වැඩේ
හරි, දැන් අපි Modules වලින් පොඩ්ඩක් ඉස්සරහට ගිහින් Packages ගැන කතා කරමු. සරලවම කිව්වොත්, Package එකක් කියන්නේ Modules (.py
files) එකතුවක්. මේ Modules එකිනෙකට සම්බන්ධ functions හෝ classes එකට group කරලා තියෙන විදියක්.
Package එකක් හදාගන්නේ කොහොමද?
පැකේජයක් කියන්නේ සාමාන්යයෙන් directories (folders) එකක්. ඒ directory එක ඇතුලේ අනිවාර්යයෙන්ම __init__.py
කියලා හිස් file එකක් හෝ code තියෙන file එකක් තියෙන්න ඕනේ. Python interpreter එකට directory එකක් Package එකක් විදියට recognize කරන්න මේ __init__.py
file එක අත්යවශ්යයි. (Python 3.3 ඉඳන් __init__.py
file එක නැතුව වුණත් package එකක් ලෙස recognize වෙනවා, නමුත් older versions වලට සහ explicit identification වලට මේක තියාගන්න එක හොඳ practice එකක්).
__init__.py
ගේ වැඩේ මොකක්ද?
__init__.py
file එකට ප්රධාන කාර්යයන් කිහිපයක් තියෙනවා:
- Directory එකක් Package එකක් ලෙස හඳුනාගැනීම: Python interpreter එක මේ file එක දැක්කොත් විතරයි ඒ directory එක Package එකක් විදියට සලකන්නේ.
- Package initialization: Package එකක් import කරනකොට මුලින්ම run වෙන්නේ මේ
__init__.py
file එකේ තියෙන code ටිකයි. මේකෙන් Package එකට අදාළ global variables initialize කරන්න, sub-modules import කරන්න, හෝ Package මට්ටමේ setup operations කරන්න පුළුවන්. - Package contents define කිරීම:
__all__
කියන list එක__init__.py
file එක ඇතුලේ define කිරීමෙන්,from package import *
වගේ statement එකකින් import වෙන්න ඕනේ modules මොනවද කියලා control කරන්න පුළුවන්.
Package Structure එකක්:
හිතන්න අපිට my_project
කියලා Package එකක් තියෙනවා. ඒකේ structure එක මෙහෙම වෙන්න පුළුවන්:
my_project/
├── __init__.py
├── calculator/
│ ├── __init__.py
│ ├── basic_ops.py
│ └── advanced_ops.py
├── utils/
│ ├── __init__.py
│ └── data_helpers.py
└── main.py
මේ උදාහරණයේදී, my_project
කියන්නේ top-level package එක. ඒක ඇතුලේ calculator
සහ utils
කියලා sub-packages දෙකක් තියෙනවා. ඒ හැම directory එකක් ඇතුලෙම __init__.py
file එකක් තියෙනවා.
Relative Imports – ලොකු Project වලට අත්යවශ්ය දෙයක්
ලොකු Packages ඇතුලේ Modules ගොඩක් තියෙනකොට, එක Module එකකින් තවත් Module එකක් import කරන්න සිද්ධ වෙනවා. මේ වෙලාවේදී අපිට Absolute Imports හෝ Relative Imports පාවිච්චි කරන්න පුළුවන්.
Absolute Imports vs. Relative Imports:
Relative Imports: මේවා current Module එකට සාපේක්ෂව path එක specify කරනවා. මේවා .
(current package) සහ ..
(parent package) වගේ dot notation පාවිච්චි කරනවා.
# my_project/calculator/advanced_ops.py එකේ ඉඳන්
from .basic_ops import add, subtract # එකම package එකේ තියෙන basic_ops module එක import කරනවා
from ..utils.data_helpers import clean_data # parent package එකේ (my_project) utils sub-package එකේ තියෙන data_helpers import කරනවා
Relative imports පාවිච්චි කරනකොට code එක readable වෙනවා, Package එකේ නම වෙනස් වුණොත් code එකේ වෙනසක් කරන්න ඕනේ වෙන්නේ නෑ.
Absolute Imports: මේවා Package එකේ top-level එකේ ඉඳන් path එක specify කරනවා.
# main.py එකේ ඉඳන්
from my_project.calculator import basic_ops
from my_project.utils import data_helpers
මේවා පැහැදිලියි, නමුත් ලොකු Packages වලදී path එක ගොඩක් දිග වෙන්න පුළුවන්.
Relative Imports භාවිතය:
දැන් අපි කලින් ගත්ත Package structure එකේ my_project/calculator/advanced_ops.py
file එකේ උදාහරණයක් බලමු:
# my_project/calculator/advanced_ops.py
from .basic_ops import add # එකම calculator package එකේ basic_ops module එකෙන් add function එක import කරනවා
def power(base, exp):
return base ** exp
def multiply_and_add(x, y, z):
# basic_ops එකෙන් add function එක පාවිච්චි කරනවා
return add(x * y, z)
මේ .
එකෙන් කියන්නේ "current package" කියන එක. ඒ කියන්නේ advanced_ops.py
තියෙන calculator
package එක ඇතුලේ basic_ops
කියන Module එකක් තියෙනවා කියන එක.
දැන් my_project/utils/data_helpers.py
එකෙන් my_project/calculator
එකේ functions පාවිච්චි කරන්න ඕනෙ නම්:
# my_project/utils/data_helpers.py
# මේක utils package එකේ ඉඳන් parent package එකට (my_project) ගිහින්, එතනින් calculator package එකට ගිහින්, basic_ops import කරනවා
from ..calculator.basic_ops import divide
def clean_data(data_list):
# data cleaning logic
print("Data cleaned!")
return [d for d in data_list if d is not None]
def process_numbers(num1, num2):
# calculator package එකෙන් divide function එක පාවිච්චි කරනවා
return divide(num1, num2)
..
කියන්නේ "parent package" කියන එක. මේක utils
package එකෙන් එලියට, ඒ කියන්නේ my_project
package එකට ගිහින්, එතනින් calculator
package එකට ඇතුල් වෙනවා කියන එකයි.
ප්රායෝගිකව කරලා බලමු: Project එකක් Organize කරමු!
හරි, දැන් අපි මේ theories ටික එකට එකතු කරලා, පොඩි Project එකක් Organize කරලා බලමු. අපිට අවශ්යයි සරල Calculator Package එකක් හදන්න. ඒකේ basic operations, advanced operations සහ main application එකක් තියෙන්න ඕනේ.
Project Structure:
my_calculator_app/
├── src/
│ ├── __init__.py
│ ├── basic_operations.py
│ ├── advanced_operations.py
│ └── utils/
│ ├── __init__.py
│ └── validation.py
└── main_app.py
Code Files:
src/__init__.py
මේක හිස් file එකක් වුණත් කමක් නෑ. Package එකක් කියලා identify කරන්න මේක අත්යවශ්යයි.
# src/__init__.py
# Can be empty, or you can import specific modules to be available directly
# from src import basic_operations # Example: to make basic_operations directly available as src.basic_operations
src/basic_operations.py
# src/basic_operations.py
def add(a, b):
return a + b
def subtract(a, b):
return a - b
def multiply(a, b):
return a * b
def divide(a, b):
if b == 0:
raise ValueError("Cannot divide by zero!")
return a / b
if __name__ == "__main__":
print("Running basic_operations directly!")
print(f"2 + 3 = {add(2, 3)}")
print(f"10 / 2 = {divide(10, 2)}")
src/advanced_operations.py
# src/advanced_operations.py
# Relative import: basic_operations module from the same 'src' package
from .basic_operations import add, multiply
# Note: No need for 'src.' prefix here because it's a relative import within the 'src' package.
def power(base, exponent):
return base ** exponent
def square_root(number):
if number < 0:
raise ValueError("Cannot calculate square root of a negative number.")
return number ** 0.5
def calculate_complex_expression(x, y, z):
# Using imported functions from basic_operations
step1 = multiply(x, y)
step2 = add(step1, z)
return step2
if __name__ == "__main__":
print("Running advanced_operations directly!")
print(f"2^3 = {power(2, 3)}")
print(f"sqrt(25) = {square_root(25)}")
print(f"Complex expression (2 * 3 + 4) = {calculate_complex_expression(2, 3, 4)}")
src/utils/__init__.py
මේකත් හිස් file එකක් වුණත් කමක් නෑ.
# src/utils/__init__.py
src/utils/validation.py
# src/utils/validation.py
def is_number(value):
return isinstance(value, (int, float))
def is_positive(value):
return value > 0
if __name__ == "__main__":
print("Running validation directly!")
print(f"Is 5 a number? {is_number(5)}")
print(f"Is 'abc' a number? {is_number('abc')}")
print(f"Is -10 positive? {is_positive(-10)}")
main_app.py
මේක තමයි අපේ Project එකේ ප්රධාන entry point එක. අපි මේකෙන් අපේ src
Package එකේ Modules import කරලා පාවිච්චි කරනවා.
# main_app.py
# Absolute imports from our 'src' package
from src.basic_operations import add, subtract
from src.advanced_operations import power, calculate_complex_expression
from src.utils.validation import is_number, is_positive
def run_calculator():
print("Welcome to My Awesome Calculator App!")
print("------------------------------------")
num1_str = input("Enter first number: ")
num2_str = input("Enter second number: ")
if not (is_number(float(num1_str)) and is_number(float(num2_str))):
print("Invalid input. Please enter numbers only.")
return
num1 = float(num1_str)
num2 = float(num2_str)
print(f"{num1} + {num2} = {add(num1, num2)}")
print(f"{num1} - {num2} = {subtract(num1, num2)}")
print(f"{num1} to the power of {num2} = {power(num1, num2)}")
# Example using a complex expression
print(f"Complex calc (5 * 2 + 7) = {calculate_complex_expression(5, 2, 7)}")
if __name__ == "__main__":
run_calculator()
print("\nCalculator app finished. Have a great day!")
Project එක Run කරන්නේ කොහොමද?
මේ Project එක run කරන්න පුළුවන් ප්රධාන ක්රම දෙකක් තියෙනවා:
Python ගේ -m
flag එක පාවිච්චි කිරීම (Module execution):
මේක තමයි Package එකක් run කරන්න තියෙන standard සහ recommended ක්රමය. Project එකේ root directory එකෙන් (මේ උදාහරණයේදී my_calculator_app/
) run කරන්න:
python -m main_app
නැත්නම්, main_app.py
file එක src
Package එක ඇතුලේ තිබුණා නම්, මෙහෙම run කරන්න පුළුවන්:
# If main_app.py was inside src/, e.g., src/main_app.py
# Then the structure would be my_calculator_app/src/main_app.py
# python -m src.main_app
-m
flag එකෙන් Python වලට කියන්නේ "මේක Module එකක් විදියට run කරන්න" කියලා. මේකෙන් Python එක automatically sys.path එකට current directory එකයි, import කරපු Package එකේ parent directory එකයි add කරනවා. ඒ නිසා අපේ imports වලට අවශ්ය path එක set වෙනවා. මේ ක්රමය විශේෂයෙන්ම, src
directory එකක් වගේ දෙයක් ඇතුලේ අපේ main script එක තියෙනවා නම් ගොඩක් වැදගත්.
main_app.py
එක direct run කිරීම:my_calculator_app
directory එකේ ඉඳන් run කරන්න:
python main_app.py
මේක වැඩ කරන්නේ main_app.py
file එක src
package එකට පිටින් තියෙන නිසා. ඒ නිසා Python interpreter එකට src
package එක හොයාගන්න පුළුවන් වෙනවා.
කරදරකාරී ImportError විසඳගනිමු සහ Best Practices
Modules සහ Packages එක්ක වැඩ කරනකොට, බහුලවම එන error එකක් තමයි ImportError
. විශේෂයෙන්ම relative imports එක්ක වැඩ කරනකොට මේක එන්න පුළුවන්. ඒ වගේම, හොඳ Project Structure එකක් Maintain කරන එකත් ගොඩක් වැදගත්.
ImportError
with Relative Imports
බොහෝ වෙලාවට මේ error එක එන්නේ, අපි Package එකක ඇතුලේ තියෙන Module එකක් direct run කරන්න ගියාමයි. උදාහරණයක් විදියට, අපේ my_calculator_app
Project එකේ, src/advanced_operations.py
file එක direct run කරන්න ගියොත්:
# my_calculator_app/src directory එකේ ඉඳන්:
python advanced_operations.py
මේකෙන් වෙන්නේ ImportError: attempted relative import with no known parent package
කියලා error එකක් එන එකයි.
මොකද, advanced_operations.py
file එක direct run කරනකොට, Python interpreter එක හිතන්නේ ඒක standalone script එකක් කියලා. ඒ වෙලාවේදී ඒකට "parent package" එකක් නෑ. Relative imports (from .basic_operations import add
වගේ) වැඩ කරන්නේ ඒ Module එක Package එකක කොටසක් විදියට import කරනකොට විතරයි.
විසඳුම:
මේක විසඳන්න පුළුවන් ක්රම දෙකක් තියෙනවා:
- Main Entry Point එකක් පාවිච්චි කිරීම:Project එකකට අනිවාර්යයෙන්ම top-level executable script එකක් (e.g.,
main_app.py
) තියෙන්න ඕනේ. මේ script එකෙන් තමයි Package එකේ අනිත් Modules import කරලා පාවිච්චි කරන්න ඕනේ. මේකෙන් Project එකේ structure එක පැහැදිලියි, ව්යාකූලතා අඩුයි.
-m
flag එකෙන් run කිරීම:my_calculator_app
root directory එකේ ඉඳන් advanced_operations.py
module එකක් විදියට run කරන්න:
python -m src.advanced_operations
මේ ක්රමයෙන් Python එකට කියනවා src
කියන්නේ Package එකක් කියලයි, advanced_operations
කියන්නේ ඒකේ Module එකක් කියලයි. එතකොට Python එක Package context එක set කරන නිසා relative imports හරියට වැඩ කරනවා.
Best Practices for Package Structure:
- සරල, පැහැදිලි structure එකක්: Package එකේ purpose එකට අනුව Modules organize කරන්න. Files ගොඩක් එක තැන තියෙනවට වඩා sub-packages වලට බෙදා වෙන් කිරීම හොඳයි.
__init__.py
file එක: Package එකක් ලෙස හඳුනාගන්න මේක අත්යවශ්යයි. හිස් වුණත් කමක් නෑ. Package level initialization කරන්න හෝ__all__
වගේ දේවල් define කරන්න පාවිච්චි කරන්න පුළුවන්.- Absolute Imports බහුලව පාවිච්චි කරන්න: සාමාන්යයෙන් absolute imports තමයි recommend කරන්නේ. මොකද ඒවා පැහැදිලියි, Module එකේ සම්පූර්ණ path එක පේන නිසා. Relative imports පාවිච්චි කරන්න පුළුවන්, එකම Package එකක් ඇතුලේ modules අතර dependencies තියෙනකොට.
- Virtual Environments: Project එකට අදාළ dependencies වෙනත් Projects වල dependencies එක්ක conflict නොවෙන්න, සෑම Project එකකටම වෙනම Virtual Environment එකක් පාවිච්චි කරන එක අත්යවශ්යයි.
venv
හෝconda
වගේ tools පාවිච්චි කරන්න. - Consistent Naming Conventions: Python වල PEP 8 guidelines අනුගමනය කරන්න. Modules වල නම් lowercase, functions වල නම් lowercase_with_underscores, classes වල නම් CamelCase වගේ දේවල්.
src/
directory එකක් පාවිච්චි කිරීම: ලොකු Projects වලදී, සියලුම source code එක src/
directory එකක් ඇතුලේ තියන එක standard practice එකක්. මේකෙන් Project root එක clear වෙනවා, tests, docs, configs වගේ දේවල් source code එකෙන් වෙන් කරලා තියන්න පුlink.
my_project/
├── src/
│ ├── my_package/
│ │ ├── __init__.py
│ │ └── module1.py
│ └── main_script.py
├── tests/
│ ├── test_module1.py
├── README.md
├── requirements.txt
මේවා තමයි Modules සහ Packages එක්ක වැඩ කරනකොට මතක තියාගන්න ඕනේ වැදගත් දේවල්. මේ concepts හරියට තේරුම් ගත්තොත්, ලොකු, complex Python Projects වුණත් පහසුවෙන් organize කරගන්නත්, maintain කරන්නත් පුළුවන්.
අවසාන කතාව!
ඉතින් කොහොමද, යාලුවනේ? අද අපි Python වල Modules සහ Packages වල ගැඹුරටම ගියා නේද? __name__ == "__main__"
ගේ කතාව, Packages හැදෙන හැටි, __init__.py
ගේ වටිනාකම, ඒ වගේම tricky වෙන්න පුළුවන් Relative imports ගැනත් අපි හොඳට ඉගෙන ගත්තා. ඒ වගේම, ImportError
වගේ කරදරකාරී errors කොහොමද විසඳගන්නේ කියලත්, හොඳ Project structure එකක් Maintain කරන්න ඕනේ Best Practices මොනවද කියලත් අපි කතා කළා.
මේ concepts ටික තේරුම් ගන්න එක ටිකක් අමාරු වුණාට, මේවා තමයි ලොකු Python Project වල Backbone එක. මේවා හරියට තේරුම් ගත්තොත්, ඔයාට තවදුරටත් පොඩි script ලියන Programmer කෙනෙක් විතරක් නෙවෙයි, ලොකු Software Systems නිර්මාණය කරන්න පුළුවන් දක්ෂ Software Engineer කෙනෙක් වෙන්න පුළුවන්.
දැන් ඔයාට කරන්න තියෙන්නේ මේවා නිකන් කියවලා නවතින්නේ නැතුව, අතින් කරලා බලන එකයි. උඩ තියෙන Project Structure එක හදලා, Code ටික ලියලා, Run කරලා බලන්න. Errors ආවොත් බය වෙන්න එපා, ඒවා තමයි අපිට හොඳටම උගන්වන්නේ. Google කරලා, Stack Overflow ගිහින් ඒවා විසඳගන්න try කරන්න. ඒක තමයි ඇත්තටම Programmer කෙනෙක් විදියට දියුණු වෙන විදිය!
මේ ගැන ඔයාගේ අදහස්, ප්රශ්න හෝ ඔයා දන්නා අමතර tips තියෙනවා නම්, පහලින් comment section එකේ share කරන්න. අපි හැමෝටම එකතු වෙලා ඉගෙන ගනිමු!
තවත් අලුත් Technical Article එකකින් හමුවෙමු, හැමෝටම සුභ දවසක්!