# Python-এর module ও package: import, pip, venv ও library সহজ ভাষায়

URL: https://skillaria.top/bn/guides/python/modules-python

Python-এর module হলো একটি .py ফাইল, package হলো module-এর ফোল্ডার, আর library হলো কয়েকটি package-এর সমষ্টি, যা import দিয়ে যুক্ত করা হয়। তৃতীয় পক্ষের library ইনস্টল হয় pip বা uv দিয়ে একটি virtual environment (venv)-এর ভেতরে — এটি একটি আলাদা ফোল্ডার, যাতে বিভিন্ন প্রজেক্টের সংস্করণ একে অন্যের সঙ্গে না মেলে।

Python-এর module হলো একটি সাধারণ কোড-ফাইল, আর `import` হলো তার থেকে ফাংশন ও ক্লাস নেওয়ার উপায়। Module থেকে package, package থেকে library তৈরি হয়। তৃতীয় পক্ষের library যেন বিভিন্ন প্রজেক্টে একে অন্যকে বাধা না দেয়, সেজন্য সেগুলো ইনস্টল হয় একটি virtual environment (venv)-এ। এখানে পুরো শৃঙ্খলটি দেখা যাক: import-এর সময় কী ঘটে, package কীভাবে গড়া, pip ও venv কীভাবে কাজ করে, এবং Python 3.15-এ আসা lazy import কী।

## Module, package, library: পার্থক্য

| ধারণা | এটি কী | উদাহরণ |
| --- | --- | --- |

| Module | একটি `.py` ফাইল; module-এর নাম = ফাইলের নাম, এক্সটেনশন বাদে | `categories.py` → `import categories` |

| Package | module ও `__init__.py` ফাইলসহ একটি ফোল্ডার | `expenses/report.py` → `from expenses.report import build` |

| Library | একটি কাজের জন্য তৈরি module ও package-এর সমষ্টি | `requests`, `pandas`, স্ট্যান্ডার্ড `pathlib` |

| Distribution (PyPI-র package) | pip যে আর্কাইভ ইনস্টল করে | `pip install requests` |

কথোপকথনে «library», «package» ও «module» শব্দগুলো প্রায়ই মিশে যায় — এটি স্বাভাবিক। গুরুত্বপূর্ণ বিষয় হলো: `import` সব সময় একটি module বা package লোড করে, আর pip PyPI থেকে একটি distribution ইনস্টল করে, যার ভেতরে থাকে package।

## Python-এ import কীভাবে কাজ করে

Import-এর কয়েকটি রূপ আছে, সবগুলোই বাস্তব কোডে দেখা যায়:

```
import math                    # পুরো module, ব্যবহার math.sqrt
from math import sqrt, pi      # নির্দিষ্ট নাম
import datetime as dt          # উপনাম
from collections import Counter as C

print(math.sqrt(16), sqrt(9), pi)
print(dt.date.today())
```

বড় library-র জন্য উপনাম সর্বজনস্বীকৃত: `import numpy as np`, `import pandas as pd`। `from module import *` এড়িয়ে চলাই ভালো: এটি নামস্থান ভরিয়ে দেয় এবং বোঝা যায় না নামটি কোথা থেকে এল।

### Import আসলে কী করে

1. `sys.modules` ক্যাশে খোঁজে। আগেই লোড হয়ে থাকলে সেটি ফেরত দেয়।
2. না থাকলে `sys.path`-এর ফোল্ডারগুলোতে ফাইল খোঁজে: চালু স্ক্রিপ্টের ফোল্ডার, স্ট্যান্ডার্ড লাইব্রেরি, এবং environment-এর site-packages।
3. পাওয়া ফাইলটি ওপর থেকে নিচে পুরোটা চালায়।
4. module অবজেক্টটি ক্যাশে রেখে নামের সঙ্গে যুক্ত করে।

এর থেকে দুটি ব্যবহারিক সিদ্ধান্ত আসে। একই module আবার `import` করলে প্রায় খরচ হয় না — কোডটি দ্বিতীয়বার চলে না। আর module-এর শীর্ষ-স্তরের সব কোড, যার মধ্যে `print` ও ভারী হিসাবও আছে, ইমপোর্টের সময়ই চলে।

```
import sys
for p in sys.path:
    print(p)
print("math" in sys.modules)
```

### if __name__ == "__main__"

Import ফাইলটি চালায়, তাই «আমাকে স্ক্রিপ্ট হিসেবে চালানো হয়েছে» এবং «আমাকে import করা হয়েছে» — এ দুটির পার্থক্য দরকার। এর জন্য আছে `__name__` ভেরিয়েবল: ফাইল সরাসরি চালালে এটি `"__main__"`, import-এ হয় module-এর নাম।

```
# categories.py
def guess(title: str) -> str:
    return "food" if "cafe" in title.lower() else "other"

if __name__ == "__main__":
    print(guess("Cafe near home"))   # শুধু python categories.py চালালে চলবে
```

Package-এর জন্য বিকল্প হলো ভেতরে `__main__.py` ফাইল রাখা এবং চালানো `python -m expenses` দিয়ে।

## স্ট্যান্ডার্ড module

Python বাক্সেই আসে «ব্যাটারি সহ»: শত শত অন্তর্নির্মিত module আলাদা ইনস্টল ছাড়াই পাওয়া যায়। সবচেয়ে ব্যবহৃত কয়েকটি:

| Module | কী কাজে |
| --- | --- |

| `os`, `sys`, `pathlib`, `shutil` | সিস্টেম, পথ, ফাইল |

| `json`, `csv`, `pickle` | ডেটা ফরম্যাট |

| `datetime`, `time`, `calendar` | তারিখ ও সময় |

| `math`, `random`, `statistics`, `fractions` | সংখ্যা |

| `re`, `string` | টেক্সট নিয়ে কাজ |

| `collections`, `itertools`, `functools` | ডেটা স্ট্রাকচার ও iterator |

| `logging`, `argparse`, `subprocess` | লগ, কমান্ড-লাইন আর্গুমেন্ট, প্রোগ্রাম চালানো |

| `asyncio`, `threading` | অ্যাসিঙ্ক্রোনাস কাজ ও থ্রেড |

স্ট্যান্ডার্ড লাইব্রেরির সব module-এর নামের তালিকা থাকে `sys.stdlib_module_names`-এ (Python 3.10+)। কোনো module-এ কী আছে দেখতে `dir(math)` ও `help(math)` ব্যবহার করুন।

## নিজের package: প্রজেক্টের কাঠামো

Module বাড়লে সেগুলোকে একটি package-এ রাখা হয়। প্রচলিত বিন্যাস হলো src-layout:

```
expenses-project/
├── pyproject.toml
└── src/
    └── expenses/
        ├── __init__.py
        ├── cli.py
        ├── parsing.py
        ├── categories.py
        └── report.py
```

Package-এর ভেতরের module একে অন্যকে import করে package-এর নাম দিয়ে (`from expenses.categories import guess`) অথবা আপেক্ষিকভাবে (`from .categories import guess`)। আপেক্ষিক import শুধু package-এর ভেতরে কাজ করে, সরাসরি স্ক্রিপ্ট হিসেবে চালানো ফাইলে নয়।

## pip: library ইনস্টল

তৃতীয় পক্ষের library থাকে PyPI-তে, আর সেগুলো বসায় pip, যা Python-এর সঙ্গে আসে। সবচেয়ে নিরাপদ উপায় pip-কে interpreter দিয়ে ডাকা — তাতে library ঠিক সেই Python-এ যায়, যেটি দিয়ে কোড চালাচ্ছেন।

```
python -m pip install requests          # ইনস্টল
python -m pip install "pandas>=2.3"     # সংস্করণের সীমা সহ
python -m pip install --upgrade requests
python -m pip uninstall requests        # মুছে ফেলা
python -m pip list                      # ইনস্টল করা package-এর তালিকা
python -m pip show requests             # সংস্করণ ও নির্ভরতা
python -m pip freeze > requirements.txt
python -m pip install -r requirements.txt
```

Windows-এ `python`-এর বদলে প্রায়ই ব্যবহৃত হয় লঞ্চার `py`। pip না পেলে সেটি বসায় অন্তর্নির্মিত module: `python -m ensurepip --upgrade`।

### জনপ্রিয় Python library

PyPI-তে কয়েক লাখ package আছে, তবে বেশির ভাগ প্রজেক্টে একই ছোট তালিকাটি বারবার আসে। অদ্ভুত কিছু খোঁজার আগে এখান থেকে শুরু করা ভালো।

| কাজ | Library |
| --- | --- |

| HTTP অনুরোধ ও API | `requests`, `httpx` |

| ডেটা বিশ্লেষণ ও টেবিল | `pandas`, `numpy` |

| গ্রাফ | `matplotlib` |

| ওয়েব সার্ভিস | `fastapi`, `django`, `flask` |

| টেস্ট | `pytest` |

| ছবি | `pillow` (import করা হয় `PIL` নামে) |

খেয়াল করুন: ইনস্টলের নাম ও import-এর নাম সব সময় মেলে না। ইনস্টল করা হয় `pip install pillow`, আর লেখা হয় `from PIL import Image`; ইনস্টল করা হয় `opencv-python`, আর import করা হয় `cv2`। ইনস্টলের পরেও `import` ব্যর্থ হলে package-এর ডকুমেন্টেশনে দেখুন তার import-এর নাম কী।

### Linux-এ library ইনস্টল

আধুনিক Debian ও Ubuntu-তে সিস্টেমের Python-এ `pip install` দিলে আসে `externally-managed-environment` ত্রুটি (PEP 668)। এটি সুরক্ষা: সিস্টেমের Python OS-এর প্যাকেজ ম্যানেজারের, pip তাকে ভাঙবে না। সঠিক সমাধান `--break-system-packages` নয়, বরং virtual environment।

## venv: virtual environment

Virtual environment হলো একটি আলাদা ফোল্ডার, যার নিজের interpreter-এর কপি (বা লিংক) এবং নিজের site-packages আছে। এর ভেতরে ইনস্টল করা library কেবল সেই প্রজেক্টেই দেখা যায়। ফলে একটি প্রজেক্টে থাকতে পারে Django 4, পাশের প্রজেক্টে Django 5 — এবং তারা একে অন্যের সঙ্গে সংঘর্ষ করে না।

`venv` module Python-এর সঙ্গেই আসে, আলাদা ইনস্টলের দরকার নেই (Debian/Ubuntu-তে কখনো কখনো সিস্টেম প্যাকেজ `python3-venv` লাগে)।

```
# .venv ফোল্ডারে environment বানানো
python -m venv .venv

# সক্রিয় করা: Linux ও macOS
source .venv/bin/activate
# সক্রিয় করা: Windows PowerShell
.venv\Scripts\Activate.ps1

# এখন pip প্যাকেজ বসাবে .venv-এর ভেতরে
python -m pip install requests
python -c "import sys; print(sys.prefix)"

# environment থেকে বের হওয়া
deactivate
```

সক্রিয় করার পরে টার্মিনালের লাইনের শুরুতে আসে `(.venv)`। Environment-এর ফোল্ডার git-এ কমিট করা হয় না (`.gitignore`-এ `.venv/` যোগ করুন), এবং মেশিনের মধ্যে কপি করা হয় না — তার বদলে নির্ভরতার তালিকা রাখা হয় এবং environment নতুন করে বানানো হয়। PowerShell সক্রিয়করণ স্ক্রিপ্ট চালাতে না দিলে ব্যবহারকারীর জন্য অনুমতি দিন: `Set-ExecutionPolicy -Scope CurrentUser RemoteSigned`।

### uv ও pyproject.toml

আধুনিক প্রজেক্টের নির্ভরতা লেখা হয় `pyproject.toml`-এ। কোর্সে ব্যবহৃত uv ম্যানেজার environment বানানো এবং ইনস্টল একসঙ্গে করে: `uv add pandas` package নামায়, `pyproject.toml`-এ লেখে এবং সঠিক সংস্করণ `uv.lock`-এ স্থির করে। সহকর্মী প্রজেক্ট ক্লোন করে `uv sync` চালালে হুবহু একই environment পায়।

```
[project]
name = "expenses"
version = "0.1.0"
requires-python = ">=3.15"
dependencies = [
    "pandas>=2.3",
]

[project.scripts]
expenses = "expenses.cli:main"
```

## Python 3.15-এ lazy import (PEP 810)

এই অধ্যায়ে 3.15-এর প্রধান নতুনত্ব — `lazy` কীওয়ার্ড। ভারী library লোড হতে সময় নেয়: কোর্সের পরিমাপে `python:3.15-slim` ইমেজে সাধারণ `import pandas` নিয়েছে প্রায় 415 ms, আর `lazy import pandas` — প্রায় 13 ms। যে CLI শুধু `--help` দেখানোর জন্য চালানো হয়, তার জন্য পার্থক্যটি বিশাল।

```
lazy import pandas as pd
lazy from expenses.report import build_report

def main() -> None:
    ...
    df = pd.read_csv(path)   # pandas-এর আসল লোড হয় এখানে
```

Module-এর বদলে নামে বসে একটি প্রক্সি অবজেক্ট (`types.LazyImportType`), আর আসল import ঘটে নামটি প্রথম ব্যবহারের সময়। যদি সেই ব্যবহার না আসে, সময়ও খরচ হয় না।

### Lazy import-এর সীমাবদ্ধতা

- শুধু module-এর শীর্ষ স্তরে অনুমোদিত: ফাংশন, ক্লাস বা `try/except`-এর ভেতরে লিখলে `SyntaxError`।
- `lazy from x import *` নিষিদ্ধ।
- `ModuleNotFoundError` শুরুতে নয়, প্রথম ব্যবহারের সময় ওঠে।
- module-এর পার্শ্বপ্রতিক্রিয়া (প্লাগইন রেজিস্টার ইত্যাদি) সময়ের দিক থেকে সরে যায়।

সব import একসঙ্গে lazy করতে পতাকা `-X lazy_imports=all` বা পরিবেশ ভেরিয়েবল `PYTHON_LAZY_IMPORTS=all`; ব্যতিক্রম ঠিক করা যায় `sys.set_lazy_imports_filter()` দিয়ে। যে কোড পুরনো সংস্করণেও চলবে, তার জন্য আছে module-ভেরিয়েবল `__lazy_modules__ = ["pandas"]`: 3.15 উল্লিখিত import-গুলো lazy করবে, আর পুরনো সংস্করণ সাধারণ `import` চালাবে। শুরুতে কোথায় সময় যায়, তা দেখায় `python -X importtime -c "import pandas"`। সবচেয়ে বেশি লাভ হয় ঘন ঘন সংক্ষিপ্ত চালু হওয়া প্রোগ্রামের; দীর্ঘ চলা সার্ভারে lazy বিশেষ কিছু বদলায় না।

## সাধারণ ভুল

- `ModuleNotFoundError: No module named 'requests'` — library অন্য Python-এ ইনস্টল হয়েছে, অথবা environment সক্রিয় নেই। একই interpreter দিয়ে `python -m pip show requests` চালিয়ে যাচাই করুন।
- নিজের ফাইলের নাম `json.py`, `random.py` বা `csv.py` — স্ক্রিপ্টের ফোল্ডার `sys.path`-এর প্রথমে থাকে, তাই সেটি স্ট্যান্ডার্ড module-কে ঢেকে দেয়। Python 3.13+ ত্রুটিতে «consider renaming» পরামর্শ দেয়। ফাইলের নাম বদলান এবং `__pycache__` মুছুন।
- বৃত্তাকার import: `a.py` `b.py`-কে import করে, আর সেটি `a.py`-কে। সাধারণ অংশ তৃতীয় module-এ রাখুন, অথবা ফাংশনের ভেতরে import করুন।
- pip চালানো হয়েছে Python-এর ভেতরে (`>>> pip install`) — পাবেন `SyntaxError`। pip-এর কমান্ড চলে টার্মিনালে।

## সারসংক্ষেপ

Module একটি ফাইল, package একটি module-এর ফোল্ডার, library তাদের তৈরি সমষ্টি; `import` প্রথমে ক্যাশে ও `sys.path`-এ খোঁজে এবং module একবারই চালায়। তৃতীয় পক্ষের library শুধু virtual environment (venv)-এর ভেতরে pip বা uv দিয়ে ইনস্টল করুন — তাতে প্রজেক্টগুলো একে অন্যকে বাধা দেয় না, এবং environment সহজে পুনরায় বানানো যায়। কোর্সে এই বিষয়টি বাস্তবে শেখানো হয়েছে: খরচের ট্র্যাকার একটি package হয়ে ওঠে, নির্ভরতা নিয়ে, এবং lazy import-এর কারণে দ্রুত শুরু হয়।

## FAQ

**প্রতিটি প্রজেক্টের জন্য কি আলাদা venv বানাতে হবে?**

হ্যাঁ, এটি ভালো অভ্যাস: প্রতিটি প্রজেক্টের library-র সংস্করণ আলাদা হতে পারে, আর আলাদা environment সংঘর্ষ এড়ায় এবং সিস্টেমের Python-কে অগোছালো করে না।

**pip ও uv-এর পার্থক্য কী?**

pip শুধু package ইনস্টল করে, আর uv environment বানায়, নির্ভরতা pyproject.toml-এ লেখে এবং সঠিক সংস্করণ lock ফাইলে স্থির রাখে; তার ওপর এটি উল্লেখযোগ্যভাবে দ্রুত।

**ইনস্টল করা Python library-র তালিকা কীভাবে দেখব?**

প্রয়োজনীয় environment-এ python -m pip list চালান; pip freeze একই তালিকা requirements.txt-এর ফরম্যাটে দেয়।

**ইনস্টল করা module কোথায় থাকে?**

বর্তমান environment-এর site-packages ফোল্ডারে; কোনো module-এর পথ দেখে __file__ অ্যাট্রিবিউট, যেমন import requests; print(requests.__file__)।

**venv ফোল্ডার কি অন্য কম্পিউটারে সরানো যায়?**

না, environment মেশিনের পথ ও interpreter-এর সঙ্গে বাঁধা; তাই নির্ভরতার তালিকা নিয়ে যান এবং নতুন করে environment বানান।


---
Source: Skillaria.Top (https://skillaria.top)
