সরাসরি পর্বে যান
পর্ব ০৭ · ৭৯-এর মধ্যে · মডিউল ২

AI-এর জন্য Python — install, uv, venv আর package

Python for AI — Installing Python, uv, venv and the Scientific Packages

Taught in Bangla, this lesson sets up a Python 3.14 environment for AI work with real uv runs: uv python install, init, add, run and the uv.lock file, then the same with venv and pip. It explains requirements.txt versus lockfiles, wheels, sdists, conda and GPU builds, reads real errors such as ModuleNotFoundError, pip install sklearn and a numpy version conflict, and shows what in-browser Pyodide can and cannot do.

এই পর্বে যা শিখবেন

  • AI আর ডেটার কাজে Python কেন এত প্রচলিত, আর তার library-গুলো কীভাবে স্তরে স্তরে সাজানো
  • কোন Python version নেবেন, আর কিছু library কেন নতুন Python-এ দেরিতে আসে
  • uv দিয়ে একটি AI প্রকল্প শুরু, package যোগ, চালানো আর lock করা — সত্যিকারের আউটপুটসহ
  • venv আর pip দিয়ে একই কাজ, আর requirements.txt বনাম lockfile-এর পার্থক্য
  • wheel, compile করা package, conda, GPU library-র মানচিত্র; সাধারণ error চেনা ও সারানো; এই কোর্সের পাতায় Python (Pyodide) কী পারে আর কী পারে না

১ · AI আর ডেটার কাজে Python কেন

মডিউল ১-এ আপনি দেখেছেন AI কী, কোথায় কাজ করে আর কোথায় ভুল করে (পর্ব ৬). এবার হাতের কাজ শুরু। প্রথম প্রশ্নটা খুব স্বাভাবিক: এত ভাষা থাকতে AI আর ডেটার কাজে প্রায় সবাই Python কেন বেছে নেন?

উত্তরটা একটু অবাক করার মতো। Python নিজে ধীর ভাষা হিসেবেই পরিচিত — একটি সাধারণ for loop C-এর তুলনায় অনেক গুণ ধীর হতে পারে। তবু AI-এর জগতে Python জিতেছে, কারণ ভারী হিসাবটা Python নিজে করে না। Python এখানে একজন দক্ষ ম্যানেজারের মতো, যিনি কাজ ভাগ করে দেন। আসল কাজ করে C, C++ আর Fortran-এ লেখা দ্রুত কোড, যা Python থেকে ডাকা যায়।

একটি বড় বিয়েবাড়ির রান্নার কথা ভাবুন। বাবুর্চি নিজের হাতে হাজার জনের পেঁয়াজ কাটেন না। তিনি সহজ ভাষায় নির্দেশ দেন — “দুই মণ পেঁয়াজ কুচি, দশ ডেকচি পোলাও” — আর দক্ষ সহকারীরা মেশিনের গতিতে কাজটা করে দেন। Python হলো বাবুর্চির সেই নির্দেশের ভাষা: পড়তে সহজ, লিখতে দ্রুত। NumPy, pandas, scikit-learn হলো সহকারীর দল, যাঁদের হাত চলে C-এর গতিতে।

এই ব্যবস্থা একদিনে তৈরি হয়নি। AI আর ডেটার কাজে যে library-গুলো আপনি এই কোর্সে বারবার দেখবেন, সেগুলো একটির ওপর আরেকটি দাঁড়িয়ে আছে। নিচের ছবিতে সবার নিচে হার্ডওয়্যার, তার ওপর দ্রুত সংখ্যা-গণনার পুরোনো library (BLAS, LAPACK), তার ওপর NumPy, তার ওপর বাকি সবাই।

AI-এর Python stack — স্তরে স্তরে

The scientific Python stack, bottom to top

AI-এর Python stack — স্তরে স্তরে আপনার কোড · notebook বাজারঘরের বিশ্লেষণ, model scikit-learn · seaborn model শেখানো, পরিসংখ্যানের chart pandas · SciPy · matplotlib টেবিল, বিজ্ঞানের হিসাব, ছবি NumPy (ndarray) সংখ্যার array — সবার ভিত্তি C / Fortran · BLAS, LAPACK compile করা দ্রুত কোড CPU · GPU আসল হিসাব এখানেই হয় uv · pip · conda: package আনে
ছবি ৭.১ — প্রতিটি স্তর নিচের স্তরের ওপর নির্ভর করে। NumPy-র version বদলালে তার ওপরের সব library-র ওপর প্রভাব পড়তে পারে — এজন্যই এই পর্বে version নিয়ে এত কথা।

ইতিহাসটা সংক্ষেপে, যতটা নিশ্চিতভাবে বলা যায়: Guido van Rossum ১৯৯১ সালে Python-এর প্রথম সংস্করণ প্রকাশ করেন। ১৯৯০-এর দশকের মাঝামাঝি Numeric নামে একটি array library তৈরি হয়, পরে আসে আরেকটি — Numarray. দুই দলের ভাগাভাগি মেটাতে Travis Oliphant দুটির ধারণা মিলিয়ে ২০০৬ সালে NumPy 1.0 প্রকাশ করেন। matplotlib শুরু করেন John D. Hunter (২০০৩ সালের দিকে)। pandas শুরু করেন Wes McKinney, ২০০৮ সালে, আর ২০০৯ সালে তা open source হয়। scikit-learn শুরু হয় ২০০৭ সালে Google Summer of Code-এর একটি প্রকল্প হিসেবে (David Cournapeau), আর ২০১০ সালে ফ্রান্সের INRIA-র একটি দল প্রথম বড় প্রকাশনা আনেন। পরে TensorFlow (২০১৫) আর PyTorch (২০১৬) Python-কে প্রধান ভাষা করে আসায় deep learning-ও Python-কেন্দ্রিক হয়ে যায়। কে কতটা কৃতিত্ব পাবেন, সে নিয়ে বিভিন্ন বিবরণে সামান্য ভিন্নতা আছে; তারিখগুলো প্রকল্পগুলোর নিজেদের ইতিহাস-পাতার কাছাকাছি।

তবে Python-ই একমাত্র উত্তর নয়। পরিসংখ্যানে R এখনো খুব শক্তিশালী, বিশেষত গবেষণা আর জীববিজ্ঞানে। Julia দ্রুত গণনার জন্য নকশা করা। ডেটা আনার কাজে SQL প্রায় অপরিহার্য (DBMS ও SQL কোর্স). Python-এর বড় সুবিধা হলো এক ভাষায় ডেটা আনা, পরিষ্কার করা, chart আঁকা, model শেখানো আর ওয়েবে চালানো — সবই করা যায়। আর এর বড় দুর্বলতা ঠিক এই পর্বের বিষয়: অনেক টুকরো, অনেক version, আর সেগুলো মিলিয়ে রাখার ঝামেলা।

মূল ধারণা

Python ভাষাটি নিজে শেখার জন্য আছে ABCL TECH-এর আলাদা Python Programming কোর্স. এখানে সেটি নতুন করে শেখানো হবে না। এই পর্বের লক্ষ্য একটাই: আপনার কম্পিউটারে এমন একটি পরিবেশ তৈরি করা, যেখানে NumPy, pandas, scikit-learn আর matplotlib ঠিক version-এ বসে, আর ছয় মাস পরেও একই ফল দেয়।

২ · কোন Python version — আর library কেন পিছিয়ে থাকে

Python প্রতি বছর অক্টোবরে একটি নতুন বড় version প্রকাশ করে, আর প্রতিটি version প্রায় পাঁচ বছর সমর্থন পায়। python.org-এর downloads পাতায় লেখার সময়ে (নভেম্বর ২০২৬) যে অবস্থা দেখা গেছে:

Versionঅবস্থাপ্রথম প্রকাশসমর্থন শেষ
3.15bugfix (নতুনতম)অক্টোবর ২০২৬২০৩১-১০
3.14bugfixঅক্টোবর ২০২৫২০৩০-১০
3.13শুধু নিরাপত্তা-সংশোধনঅক্টোবর ২০২৪২০২৯-১০
3.12শুধু নিরাপত্তা-সংশোধনঅক্টোবর ২০২৩২০২৮-১০
3.10সমর্থন শেষঅক্টোবর ২০২১২০২৬-১০

তাহলে নতুনতমটাই কেন নয়? কারণ Python নিজে আসার পর NumPy, pandas, SciPy-এর মতো compile করা library-গুলোকে নতুন version-এর জন্য আলাদা করে build করে প্রকাশ করতে হয়। Python-এর ভেতরের C-ইন্টারফেস (ABI) প্রতিটি বড় version-এ একটু বদলায়, তাই 3.14-এর জন্য বানানো ফাইল 3.15-এ চলে না। ফাইলের নামেই এটি লেখা থাকে: cp314 মানে CPython 3.14-এর জন্য।

লেখার সময়ে আমরা নিজে যাচাই করেছি। uv.lock ফাইলে (একটু পরেই দেখবেন) numpy 2.5.4, pandas 3.1.0, scikit-learn 1.9.1, matplotlib 3.11.2 আর scipy 1.18.1 — প্রতিটির জন্য cp314 আর cp315 দুই রকম ফাইলই আছে। PyPI-তে PyTorch 2.15.0-এরও cp315 আছে। কিন্তু TensorFlow-এর তখনকার সর্বশেষ স্থিতিশীল version 2.21.0-এর ফাইল ছিল শুধু cp310 থেকে cp313 পর্যন্ত। Python 3.14-এর একটি প্রকল্পে সেটি যোগ করতে চাইলে uv সরাসরি বলে দেয় কেন হবে না।

সত্যিকারের run (uv 0.13.7, Python 3.14.10; লম্বা লাইন ছাঁটা):

$ uv add "tensorflow==2.21.0"
error: Failed to add dependencies
  cause: Because tensorflow==2.21.0 has no wheels with a matching Python
  version tag (e.g., `cp314`) and your project depends on tensorflow==2.21.0,
  we can conclude that your project's requirements are unsatisfiable.
…
hint: Wheels are available for `tensorflow` (v2.21.0) with the following
Python ABI tags: `cp310`, `cp311`, `cp312`, `cp313`
এই কোর্সের সিদ্ধান্ত

এই কোর্সে Python 3.14. কারণ তিনটি: (১) কোর্সের পাতায় যে Python চলে, সেটিও 3.14, তাই পাতা আর আপনার কম্পিউটারের আচরণ মিলবে; (২) আমাদের দরকারি সব library-র 3.14-এর ফাইল আছে; (৩) এটি এখনো bugfix পর্যায়ে, ২০৩০ পর্যন্ত সমর্থন পাবে। আপনার কাজে কোনো বিশেষ library লাগলে নিয়মটা সহজ: আগে সেই library-র ইনস্টল-পাতায় বা PyPI-তে দেখুন কোন Python version সমর্থিত, তারপর Python বাছুন। উল্টোটা নয়।

আরেকটি নতুন জিনিস চোখে পড়তে পারে: 3.14t বা cp314t. এখানে “t” মানে free-threaded build — Python-এর পুরোনো GIL (একসঙ্গে একটিই thread Python কোড চালাতে পারে, এমন তালা) ছাড়া একটি বিকল্প রূপ। এটি এখনো তুলনামূলক নতুন; শেখার শুরুতে সাধারণ build-ই নিন।

৩ · Python install — Windows, macOS আর Linux

Python ইনস্টলের বিস্তারিত ধাপ (PATH, REPL, VS Code) আছে Python কোর্সের সেটআপ পর্বে. এখানে শুধু AI-এর কাজের জন্য সংক্ষেপ। দুটি পথ আছে: Python আলাদা করে ইনস্টল করা, অথবা uv-কে দিয়ে Python নামানো (অংশ ৪)। নতুনদের জন্য দ্বিতীয় পথটি প্রায়ই সহজ, কারণ এক টুলেই সব হয়। নিচের কমান্ডগুলো উদাহরণ — macOS আর Linux-এর কমান্ড এই লেখার জন্য চালানো হয়নি, আর ইনস্টলারের ধরন সময়ের সাথে বদলায়, তাই অফিসিয়াল পাতা দেখে নিন।

Python 3.14 থেকে python.org Windows-এর জন্য নতুন Python install manager সুপারিশ করে, যা Microsoft Store থেকে বা python.org-এর MSIX ফাইল থেকে আসে। পুরোনো ধাঁচের পূর্ণ installer 3.14 থেকে deprecated, আর python.org-এর ডকুমেন্টেশন অনুযায়ী 3.16 থেকে আর তৈরি হবে না।

py install 3.14       # একটি runtime নামানো
py list               # কী কী ইনস্টল আছে
py -V:3.14 -m venv .venv

python.org-এর macOS installer, অথবা Homebrew থাকলে নিচের লাইন। macOS-এর সাথে আসা পুরোনো বা সিস্টেমের Python-এ হাত না দেওয়াই ভালো।

brew install python@3.14
python3.14 --version

Ubuntu বা Debian-এ সিস্টেমের Python অপারেটিং সিস্টেমের নিজের কাজে লাগে, তাই সেখানে সরাসরি pip install করলে externally-managed-environment error আসে (বিস্তারিত Python কোর্সে). distribution-এর Python-এর version পুরোনো হতে পারে; তখন uv দিয়ে নতুন Python নামানোই সহজ।

python3 --version         # সিস্টেমে কোনটি আছে
sudo apt install python3-venv
uv python install 3.14    # অথবা uv দিয়ে আলাদা Python

একই কম্পিউটারে একাধিক Python থাকা স্বাভাবিক — সমস্যা হয় যখন আপনি জানেন না কোনটি চলছে। প্রতিটি প্রকল্পের শুরুতে একবার python --version আর অংশ ৭-এর ছোট যাচাই চালিয়ে নিন। এই এক মিনিট পরে অনেক ঘণ্টা বাঁচায়।

৪ · uv দিয়ে বাজারঘরের AI প্রকল্প — init, add, run, lock

uv হলো Astral নামের একটি কোম্পানির Rust-এ লেখা টুল, ২০২৪ সালে প্রকাশিত। এটি একাই কয়েকটি পুরোনো টুলের কাজ করে: Python নামানো, virtual environment বানানো, package ইনস্টল, আর lockfile লেখা। লেখার সময়ে PyPI-তে uv-এর সর্বশেষ version ছিল 0.13.7 (docs.astral.sh/uv-এ কমান্ডগুলোর বিবরণ আছে)। Version নম্বর ১-এর নিচে মানে টুলটি এখনো দ্রুত বদলাচ্ছে; কমান্ডের আচরণ মাঝে মাঝে বদলাতে পারে।

পাড়ার মুদি দোকানের হিসাব খাতার কথা ভাবুন। pyproject.toml হলো আপনার বাজারের ফর্দ: “চাল, ডাল, তেল” — কোন ব্র্যান্ড বা কত কেজি তা মোটামুটি। আর uv.lock হলো দোকানির পাকা রসিদ: কোন ব্র্যান্ডের কোন প্যাকেট, কত গ্রাম, কোন ব্যাচ নম্বর। ফর্দ দিয়ে আবার বাজার করলে একটু আলাদা জিনিস আসতে পারে; রসিদ দেখিয়ে আনলে হুবহু একই জিনিস।

প্রথম ধাপ: Python আর প্রকল্প

নিচের সব আউটপুট এই পর্ব লেখার জন্য একটি Windows কম্পিউটারে চালানো সত্যিকারের run — uv 0.13.7, Python 3.14.10. কম্পিউটারের আসল ফোল্ডারের নাম সরিয়ে ~/bazarghar-ai লেখা হয়েছে। সময়গুলো একটি local run-এর, ইন্টারনেটের গতির ওপর অনেকটা নির্ভর করে; এগুলো কোনো সাধারণ benchmark নয়।

$ uv python install 3.14
Downloading cpython-3.14.10-windows-x86_64-none (download) (22.2MiB)
 Downloaded cpython-3.14.10-windows-x86_64-none (download)
Installed Python 3.14.10 in 8.31s
 + cpython-3.14.10-windows-x86_64-none

$ uv init bazarghar-ai --python 3.14
Initialized project `bazarghar-ai` at `~/bazarghar-ai`

$ cd bazarghar-ai
$ ls -A
.python-version  README.md  pyproject.toml  src

দুটি কথা খেয়াল করুন। এক, uv init নিজে থেকে একটি Git repository-ও খোলে (Git আছে এমন কম্পিউটারে) আর আপনার Git-এর নাম-ইমেইল থেকে authors ঘর পূরণ করে; এই run-এ সেটি এড়াতে --vcs none --author-from none যোগ করা হয়েছিল, যাতে ব্যক্তিগত তথ্য আউটপুটে না আসে। দুই, uv-এর এই version একটি src/bazarghar_ai/ ফোল্ডারসহ package-ধাঁচের কাঠামো বানিয়েছে; আগের কিছু version শুধু একটি main.py বানাত। Version বদলালে এমন খুঁটিনাটি বদলায় — এজন্যই আউটপুট নিজের চোখে দেখা দরকার। .python-version ফাইলে লেখা আছে শুধু 3.14; uv এটি দেখে ঠিক করে প্রকল্পে কোন Python লাগবে।

দ্বিতীয় ধাপ: চারটি package যোগ করা

$ uv add numpy pandas scikit-learn matplotlib
Using CPython 3.14.10
Creating virtual environment at: .venv
Resolved 19 packages in 1.20s
Downloading pillow (6.9MiB)
Downloading numpy (12.1MiB)
Downloading scipy (35.6MiB)
Downloading pandas (10.4MiB)
…
Prepared 19 packages in 41.69s
Installed 19 packages in 1.00s
 + matplotlib==3.11.2
 + numpy==2.5.4
 + pandas==3.1.0
 + scikit-learn==1.9.1
 + scipy==1.18.1
 …
real    0m43.944s

আপনি চেয়েছেন চারটি package, এলো ১৯টি (নিজের প্রকল্পসহ)। বাকিগুলো transitive dependency — আপনার চাওয়া package-গুলোর (আপনার সরাসরি dependency) নিজেদের প্রয়োজন। যেমন scikit-learn-এর লাগে scipy, joblib আর threadpoolctl; matplotlib-এর লাগে pillow, fonttools, kiwisolver. এবার pyproject.toml খুললে দেখবেন uv নিজে থেকে নিচের সীমা লিখে দিয়েছে:

requires-python = ">=3.14"
dependencies = [
    "matplotlib>=3.11.2",
    "numpy>=2.5.4",
    "pandas>=3.1.0",
    "scikit-learn>=1.9.1",
]

এগুলো version specifier: “অন্তত এই version”. কিন্তু হুবহু কোনটি বসেছে, transitive dependency-সহ, সেটি আছে uv.lock-এ। ৫৭৩ লাইনের ফাইলটির একটি অংশ:

[[package]]
name = "numpy"
version = "2.5.4"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "…/numpy-2.5.4.tar.gz", hash = "sha256:9a94cf75…", … }
wheels = [
    { url = "…/numpy-2.5.4-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:ffa6ce09…", … },
    { url = "…/numpy-2.5.4-cp314-cp314-manylinux_2_27_x86_64…whl", hash = "sha256:d5494208…", … },
    …

লক্ষ করুন, একটি Windows কম্পিউটারে তৈরি lockfile-এ macOS আর Linux-এর ফাইলও আছে। uv-এর lockfile cross-platform: একবার lock করলে অন্য OS-এর সহকর্মীও একই version পাবেন। প্রতিটি ফাইলের sha256 hash থাকায় পথে কেউ ফাইল বদলালে ইনস্টল আটকে যাবে।

তৃতীয় ধাপ: চালানো

প্রকল্পে একটি ছোট যাচাই-স্ক্রিপ্ট check_env.py রাখা হলো, যা Python আর package-গুলোর version ছাপে, তারপর seed দিয়ে বাজারঘরের পাঁচ দিনের কাল্পনিক বিক্রি বানায়:

import sys
from importlib.metadata import version

import numpy as np

print("Python", sys.version.split()[0])
for pkg in ["numpy", "pandas", "scikit-learn", "matplotlib", "scipy"]:
    print(f"{pkg:13} {version(pkg)}")

rng = np.random.default_rng(42)
sales = rng.integers(100, 1000, size=5)
print("sales:", sales, "total:", sales.sum())
$ uv run check_env.py
Python 3.14.10
numpy         2.5.4
pandas        3.1.0
scikit-learn  1.9.1
matplotlib    3.11.2
scipy         1.18.1
sales: [180 796 689 494 489] total: 2648
real    0m0.813s

uv run-এর জন্য virtual environment “activate” করতে হয় না। প্রতিবার চালানোর আগে uv দেখে নেয় pyproject.toml, uv.lock আর .venv — তিনটি মিলছে কি না; না মিললে আগে ঠিক করে, তারপর চালায়। একই কমান্ড অন্য কেউ চালালে তাঁর কম্পিউটারেও ঠিক এই version-গুলো বসবে, আর seed একই হওয়ায় sales-এর সংখ্যাও একই আসার কথা।

নিচের ডায়াগ্রামে uv add-এর ভেতরের ধাপগুলো দেখুন। প্রতিটি সংখ্যা উপরের সত্যিকারের run থেকে।

  1. ফর্দpyproject৪টি নাম
  2. Resolve1.20s১৯টি package
  3. Lockuv.lockহুবহু version
  4. নামানো41.69scache-এ
  5. বসানো.venv1.00s
pyproject.tomlআপনি যা চাইলেন
$ uv add numpy pandas \
         scikit-learn matplotlib
dependencies-এ ৪টি নাম যোগ হবে
ResolverPyPI-র তথ্য মিলিয়ে
scikit-learn → scipy,
  joblib, threadpoolctl
matplotlib → pillow, …
pandas → numpy, tzdata …
Resolved 19 packages in 1.20s
uv.lock৫৭৩ লাইন
name = "numpy"
version = "2.5.4"
wheels: win, mac, linux
hash = "sha256:…"
Downloadcache খালি ছিল
scipy  35.6MiB
numpy  12.1MiB
pandas 10.4MiB …
Prepared 19 packages in 41.69s
.venvপ্রকল্পের নিজের তাক
Installed 19 packages in 1.00s
মোট সময়: 43.9s
নতুন প্রকল্পে আবার: 1.1s
  1. ফর্দ লেখা। uv add প্রথমে আপনার চাওয়া চারটি নাম pyproject.toml-এর dependencies-এ লেখে। এটি বাজারের ফর্দ — শুধু নাম আর সীমা।
  2. Resolve. uv-এর dependency resolver PyPI থেকে প্রতিটি package-এর প্রয়োজনের তালিকা আনে আর এমন একটি version-সেট খোঁজে যা সবার শর্ত মেটায়। চারটি নাম থেকে দাঁড়াল ১৯টি package; সময় লাগল ১.২০ সেকেন্ড।
  3. Lock. খুঁজে পাওয়া সেটটি হুবহু লেখা হলো uv.lock-এ: প্রতিটি package-এর version, উৎস, প্রতিটি OS-এর ফাইল আর তার hash. এটিই পাকা রসিদ।
  4. নামানো। দরকারি wheel ফাইল নামিয়ে uv তার নিজের cache-এ রাখল। cache খালি থাকায় এই ধাপেই সবচেয়ে বেশি সময় — ৪১.৬৯ সেকেন্ড, প্রায় পুরোটাই ইন্টারনেটে নামানো।
  5. বসানো। cache থেকে ফাইলগুলো প্রকল্পের .venv-এ বসল ১.০০ সেকেন্ডে; মোট সময় ৪৩.৯ সেকেন্ড। পরে আরেকটি নতুন প্রকল্পে একই চার package যোগ করতে লাগল মাত্র ১.১ সেকেন্ড, কারণ সব ফাইল তখন cache-এ।
কমান্ডকী করে
uv python install 3.14uv-এর নিজের ফোল্ডারে একটি Python নামায়
uv init নামনতুন প্রকল্প: pyproject.toml, .python-version
uv add pkg / uv remove pkgpackage যোগ বা বাদ; lock আর .venv একসঙ্গে হালনাগাদ
uv run file.pyসব মিলিয়ে নিয়ে প্রকল্পের পরিবেশে চালায়
uv sync --lockedঅন্য কম্পিউটারে lockfile থেকে হুবহু পরিবেশ বানায়; lock পুরোনো হলে থামে
uv tree --depth 1কোন package কার কারণে এলো, তার গাছ

৫ · একই কাজ venv আর pip দিয়ে — requirements.txt বনাম lockfile

uv নতুন; অনেক প্রতিষ্ঠান, পুরোনো টিউটোরিয়াল আর সার্ভারে এখনো চলে Python-এর সাথে আসা দুই টুল: venv আর pip. এগুলো কীভাবে কাজ করে — activate, PATH, site-packages — বিস্তারিত আছে Python কোর্সের pip আর venv পর্বে. এখানে শুধু AI-এর একই চার package দিয়ে পাশাপাশি তুলনা।

সত্যিকারের run (একই কম্পিউটার, uv-এর নামানো Python 3.14.10, venv-এর সাথে আসা pip 26.2.2; Windows-এ Git Bash থেকে, তাই activate-এর পথ Scripts):

$ python -m venv .venv                        # 2.7s
$ source .venv/Scripts/activate               # macOS/Linux: .venv/bin/activate
(.venv) $ pip install numpy pandas scikit-learn matplotlib
…
Successfully installed cloudpickle-3.1.2 contourpy-1.4.0 … matplotlib-3.11.2
narwhals-2.28.0 numpy-2.5.4 … pandas-3.1.0 … scikit-learn-1.9.1 scipy-1.18.1 …
real    1m25.902s
(.venv) $ pip freeze > requirements.txt
(.venv) $ head -4 requirements.txt
cloudpickle==3.1.2
contourpy==1.4.0
cycler==0.12.1
fonttools==4.68.0

একই ১৮টি package (নিজের প্রকল্প বাদে), একই version. পার্থক্য সময়ে আর রেকর্ডে। এক নজরে, একই দিনের একটি local run-এ:

কাজuvvenv + pip
পরিবেশ বানানোuv add-এর ভেতরেই২.৭ সেকেন্ড
চার package, cache খালি৪৩.৯ সেকেন্ড১ মিনিট ২৫.৯ সেকেন্ড
একই সেট, cache ভরা, নতুন পরিবেশে১.১ সেকেন্ড (uv add); ১.৩ সেকেন্ড (uv pip install -r)১৮.৭ সেকেন্ড (pip install -r)

cache খালি থাকলে দুই টুলের সময়ই মূলত ইন্টারনেটে ফাইল নামানোর সময়, তাই সেখানে তুলনা খুব নির্ভরযোগ্য নয় — অন্য সময় বা অন্য নেটওয়ার্কে সংখ্যা বদলাবে। cache ভরা থাকলে পার্থক্য স্পষ্ট, কারণ uv ফাইলগুলো cache থেকে link বা দ্রুত copy করে, আর pip প্রতিটি wheel খুলে আবার বসায়। আপনার কাজে এই ১৭ সেকেন্ড বড় ব্যাপার কি না, তা নির্ভর করে আপনি দিনে কতবার পরিবেশ বানান তার ওপর (যেমন CI-তে প্রতিবার)।

requirements.txt বনাম lockfile — আসল পার্থক্য

📃 requirements.txt (pip freeze)

একটি সাধারণ তালিকা: নাম==version. যে কম্পিউটারে freeze করা হলো, শুধু সেখানকার ছবি। কোনটি আপনি নিজে চেয়েছিলেন আর কোনটি সাথে এসেছে, তা আলাদা করা যায় না। hash নেই, অন্য OS-এর তথ্য নেই।

সরল, সব জায়গায় চলে

🔒 uv.lock

সরাসরি চাওয়া আর সাথে আসা package আলাদা; প্রতিটির উৎস, প্রতিটি OS-এর ফাইল আর hash. uv sync --locked lockfile পুরোনো হলে থেমে যায়। হাতে সম্পাদনা করার জিনিস নয়।

পূর্ণ রসিদ, যাচাইযোগ্য

দুই জগতের মধ্যে সেতুও আছে। uv থেকে pip-এর জন্য তালিকা বানাতে uv export --format requirements.txt; আর ২০২৫ সালে গৃহীত PEP 751 একটি মানক lockfile ফরম্যাট দিয়েছে (pylock.toml), uv যেটি --format pylock.toml দিয়ে export করতে পারে। অর্থাৎ lockfile-এর ধারণা আর কোনো এক টুলের নিজস্ব নয়। প্রকল্পের ফোল্ডার, lockfile আর Git-এ কী রাখবেন, তার পূর্ণ অভ্যাস আসবে পর্ব ১২-এ (পুনরুৎপাদনযোগ্য প্রকল্প)।

এবার activate আসলে কী বদলায়, তা ধাপে ধাপে দেখুন। ফোল্ডারের আসল নাম এখানে দেখানো হচ্ছে না; শুধু কোন জায়গা আগে খোঁজা হয়, সেটি।

1cd ~/bazarghar-ai2python -m venv .venv3source .venv/bin/activate4python check_env.py5deactivate6python check_env.py
পরিবেশের অবস্থা
prompt
PATH-এর প্রথম ঘর
python মানে
numpy পাবে?
  1. প্রকল্পের ফোল্ডারে। এখনো কিছু বদলায়নি। python লিখলে shell PATH-এর ফোল্ডারগুলো ক্রমে খুঁজে প্রথম যে Python পায় সেটিই চালায় — এখানে সিস্টেমের Python.
  2. venv বানানো। .venv ফোল্ডারে একটি নতুন, খালি পরিবেশ তৈরি হলো, ভেতরে নিজস্ব python আর ফাঁকা site-packages. কিন্তু PATH এখনো আগের মতো, তাই python এখনো সিস্টেমেরটাই।
  3. Activate. একমাত্র বড় বদল: PATH-এর একেবারে শুরুতে .venv/bin (Windows-এ .venv\Scripts) বসল, আর prompt-এর সামনে এলো (.venv). এখন python মানে venv-এর Python. ধরে নেওয়া হচ্ছে আপনি এরপর এখানে pip install করে numpy বসিয়েছেন।
  4. চালানো। venv-এর Python তার নিজের site-packages-এ numpy 2.5.4 পেল, স্ক্রিপ্ট চলল। এই একই কাজ uv run activate ছাড়াই করে।
  5. Deactivate. PATH আগের অবস্থায় ফিরল, prompt থেকে (.venv) চলে গেল। venv-এর ফোল্ডার মোছেনি; শুধু আর আগে খোঁজা হচ্ছে না।
  6. আবার চালানো — ভুল জায়গায়। এবার সিস্টেমের Python চলল, যার কাছে numpy নেই: ModuleNotFoundError. package ইনস্টল আছে, কিন্তু অন্য Python-এ। সবচেয়ে সাধারণ এই ভুলটির পুরো আলোচনা অংশ ৭-এ।

৬ · Wheel, compile করা package, conda আর GPU

NumPy বা SciPy-এর ভেতরে প্রচুর C, C++ আর Fortran কোড। এমন কোড কোনো কম্পিউটারে চালাতে হলে আগে compile করতে হয় — অর্থাৎ ওই OS আর CPU-র machine code বানাতে হয় (C কোর্সের toolchain পর্বে এই প্রক্রিয়া আছে)। তাই PyPI-তে একটি package দুইভাবে থাকতে পারে:

🎁 Wheel (.whl)

আগে থেকে build করা, শুধু খুলে বসালেই চলে। নামেই লেখা কোন Python আর কোন OS-এর জন্য। ইনস্টলে compiler লাগে না।

numpy-2.5.4-cp314-cp314-win_amd64.whl

🧱 sdist (.tar.gz)

শুধু সোর্স কোড। আপনার কম্পিউটারেই build করতে হয়, তাই C/Fortran compiler আর দরকারি library লাগে। না থাকলে ব্যর্থ।

numpy-2.5.4.tar.gz

wheel-এর নামের শেষ তিন অংশকে বলে wheel tag: Python (cp314 = CPython 3.14), ABI (cp314), আর platform (win_amd64 = ৬৪-বিট Windows; manylinux_2_27_x86_64 = বেশিরভাগ আধুনিক ৬৪-বিট Linux; macosx_11_0_arm64 = Apple Silicon Mac). ইনস্টলার নিজের Python আর OS-এর সাথে মেলে এমন wheel খোঁজে; না পেলে sdist নিয়ে build করার চেষ্টা করে। তখনই সমস্যা শুরু হয়।

নিজের চোখে দেখা যাক। NumPy 1.26.4 প্রকাশিত হয়েছিল ২০২৪ সালের শুরুতে, Python 3.14 আসার অনেক আগে, তাই এর কোনো cp314 wheel নেই। একটি আলাদা ছোট প্রকল্পে Python 3.14-এ numpy<2 চাইলে:

সত্যিকারের run (Python 3.14.10, uv 0.13.7; build-এর লম্বা লগ ছাঁটা, ফোল্ডারের নাম সরানো):

$ uv add "numpy<2"
Resolved 2 packages in 2ms
   Building numpy==1.26.4
error: Failed to add dependencies
  cause: Failed to build `numpy==1.26.4`
  cause: The build backend returned an error
  cause: Call to `mesonpy.build_wheel` failed (exit code: 1)
…
         Project name: NumPy
         Project version: 1.26.4
…
         ..\meson.build:1:0: ERROR: Compiler cl cannot compile programs.
…
hint: Build failures usually indicate a problem with the package or the build environment

uv wheel না পেয়ে সোর্স থেকে NumPy build করতে গেল, আর এই কম্পিউটারে C compiler ঠিকমতো সাজানো না থাকায় ব্যর্থ হলো। পনেরো বছর আগে Windows-এ বিজ্ঞানের Python বসানো মানে প্রায় প্রতিবারই এই অভিজ্ঞতা — সাথে Fortran compiler, BLAS library খোঁজা, আর ঘণ্টার পর ঘণ্টা। তখন অনেকে নির্ভর করতেন স্বেচ্ছাসেবীদের বানানো অনানুষ্ঠানিক Windows binary-র ওপর। পরিস্থিতি বদলায় ধাপে ধাপে: ২০১২–১৩ সালে wheel ফরম্যাট (PEP 427), ২০১৬ সালে Linux-এর জন্য manylinux মান (PEP 513), আর বড় প্রকল্পগুলোর স্বয়ংক্রিয় build ব্যবস্থা। আজ প্রায় সব জনপ্রিয় OS আর Python version-এর জন্য wheel থাকে — শর্ত একটাই, version-গুলো একে অপরের সমসাময়িক হতে হবে।

wheel পেলে ইনস্টল কয়েক সেকেন্ডের কাজ।
wheel না পেলে আপনার কম্পিউটার নিজেই কারখানা — compiler না থাকলে কাজ বন্ধ।

conda আর mamba — কখন দরকার

conda (২০১২ সালে Continuum Analytics, এখনকার Anaconda থেকে আসে) একটি আলাদা জগৎ। এটি PyPI থেকে নয়, নিজের channel থেকে package আনে, আর শুধু Python package নয়, Python-এর বাইরের জিনিসও বসায়: C/C++ library, compiler, CUDA toolkit, GDAL-এর মতো ভূগোলের library, এমনকি R. সম্প্রদায়-চালিত সবচেয়ে বড় channel হলো conda-forge. mamba হলো conda-র একটি দ্রুত, C++-এ নতুন করে লেখা রূপ; conda-র নতুন version-গুলোও ডিফল্টভাবে mamba-র solver (libmamba) ব্যবহার করে বলে জানা যায়।

  • conda ভালো যখন: আপনার কাজে এমন non-Python library লাগে যার wheel নেই বা ঝামেলার (ভূগোল, bioinformatics, কিছু GPU stack), অথবা প্রতিষ্ঠান আগে থেকেই conda ব্যবহার করে।
  • uv/pip ভালো যখন: আপনার সব package PyPI-তে wheel হিসেবে আছে — এই কোর্সের পুরো stack-এর ক্ষেত্রে তাই।
  • সাবধানতা: একই পরিবেশে conda আর pip মেশালে কোনটি কোন ফাইল বসিয়েছে, তা গুলিয়ে যায়। আর Anaconda কোম্পানির নিজস্ব repository বড় প্রতিষ্ঠানে ব্যবহারে বাণিজ্যিক লাইসেন্সের শর্ত আছে বলে জানা যায়; ব্যবহারের আগে সর্বশেষ শর্ত নিজে পড়ে নিন। conda-forge-এর জন্য Miniforge installer প্রচলিত।

conda বা mamba এই পর্ব লেখার জন্য চালানো হয়নি, কারণ এই কোর্সের কোনো কাজে তাদের প্রয়োজন নেই। নিচেরটি তাই উদাহরণ, আউটপুট ছাড়া:

conda create -n bazarghar -c conda-forge python=3.14 numpy pandas scikit-learn matplotlib
conda activate bazarghar

GPU library — শুধু দিকনির্দেশ

এই কোর্সের প্রায় সব কাজ সাধারণ ল্যাপটপের CPU-তেই চলে। deep learning-এ GPU লাগলে (পরে আলাদা Deep Learning কোর্সে) মনে রাখবেন: PyTorch-এর মতো library-র GPU-রূপ সাধারণ PyPI ইনস্টলের চেয়ে একটু আলাদা হতে পারে — NVIDIA GPU-র জন্য CUDA-যুক্ত build, AMD-এর জন্য ROCm, Apple Silicon-এ Metal. সঠিক কমান্ড পেতে প্রতিটি প্রকল্পের অফিসিয়াল install-পাতা দেখুন (PyTorch-এর ওয়েবসাইটে OS আর GPU বেছে কমান্ড পাওয়া যায়)। ড্রাইভার, CUDA version আর library version — তিনটি মিলতে হয়। এই লেখা যে কম্পিউটারে তৈরি, সেখানে GPU নেই, তাই কোনো GPU আউটপুট এখানে দেখানো হচ্ছে না।

৭ · ভেতর থেকে version যাচাই আর তিনটি সাধারণ error

Python-এর ভেতর থেকে version দেখা

দুটি উপায় আছে, আর দুটির পার্থক্য জানা দরকার:

  • numpy.__version__ — module import করে তার নিজের লেখা version পড়া। প্রচলিত, কিন্তু সব package এটি রাখে না, আর import করতে হয়।
  • importlib.metadata.version("scikit-learn") — import না করে ইনস্টল-তথ্য থেকে পড়া। এখানে নাম দিতে হয় distribution-এর নাম, যে নামে ইনস্টল করেছেন: scikit-learn, যদিও import করেন sklearn নামে। pillow ইনস্টল করে import করেন PIL.

Error ১ — ModuleNotFoundError: “ইনস্টল তো করেছিলাম!”

একই check_env.py, কিন্তু প্রকল্পের venv বাদ দিয়ে uv-এর নামানো সাধারণ Python দিয়ে চালানো হলো (-s দিয়ে ব্যবহারকারীর নিজস্ব package-ফোল্ডারও বাদ):

$ python -s check_env.py
Traceback (most recent call last):
  File "~/bazarghar-ai/check_env.py", line 4, in <module>
    import numpy as np
ModuleNotFoundError: No module named 'numpy'

package ইনস্টল আছে, কিন্তু .venv-এর ভেতরে; এই Python সেখানে খোঁজেই না। সমাধান: uv run check_env.py, অথবা আগে venv activate. pip ব্যবহার করলে সবসময় python -m pip install … লিখুন, শুধু pip নয় — তাতে নিশ্চিত হন যে package যাচ্ছে ঠিক সেই Python-এ, যেটি আপনি চালাবেন।

এর চেয়েও বিপজ্জনক একটি রূপ এই run-এই ধরা পড়েছে। -s ছাড়া একই Python চালালে error আসেনি, এসেছে numpy 2.5.1 — কারণ এই কম্পিউটারে কখনো pip install --user numpy করা হয়েছিল, আর সেই ব্যবহারকারী-ফোল্ডার একই minor version-এর সব Python ভাগ করে নেয়। তারপর স্ক্রিপ্ট থামল pandas-এ এসে (PackageNotFoundError: No package metadata was found for pandas). অর্থাৎ ভুল পরিবেশ সবসময় error দেয় না; কখনো চুপচাপ অন্য version চালায়। এজন্যই প্রতিটি AI প্রকল্পে শুরুতে version ছাপা একটি ভালো অভ্যাস।

Error ২ — ভুল নাম: pip install sklearn

import-এর নাম আর ইনস্টলের নাম গুলিয়ে ফেলা খুব সাধারণ। PyPI-তে sklearn নামের package-টি একটি পুরোনো বিকল্প নাম, যা scikit-learn দল ইচ্ছে করে ইনস্টলে error দেওয়ার মতো করে রেখেছে। সত্যিকারের run (ছাঁটা):

$ uv pip install sklearn
error: Failed to build `sklearn==0.0.post12`
…
         The 'sklearn' PyPI package is deprecated, use 'scikit-learn'
         rather than 'sklearn' for pip commands.
…
hint: `sklearn` is often confused for `scikit-learn`. Did you mean to install `scikit-learn` instead?

Error ৩ — version conflict

ধরুন বাজারঘরের পুরোনো একটি বিক্রির পূর্বাভাসের কোড NumPy 1.x-এ লেখা, আর কেউ ভাবলেন “numpy<2 দিলেই সব ঠিক”। কিন্তু প্রকল্পে আগেই pandas 3.1 আছে। নিচের ডায়াগ্রামে দ্বন্দ্বটি কীভাবে ধরা পড়ল আর কীভাবে মিটল, ধাপে ধাপে দেখুন। ধাপ ২ আর ৫-এর আউটপুট সত্যিকারের run থেকে।

  1. চাওয়াnumpy<2পুরোনো কোডের জন্য
  2. Resolverunsatisfiableমিল নেই
  3. কারণ পড়া≥2.3.3 বনাম <2ফাঁকা ছেদ
  4. বিকল্পA বা Bখরচ মেপে
  5. মীমাংসাuv lock --check১৯টি, ঠিক
Terminalচাওয়া
$ uv add "numpy<2"
আগে থেকে আছে:
pandas>=3.1.0
uvসত্যিকারের আউটপুট
Because pandas>=3.1.0
depends on numpy>=2.3.3
and your project depends
on numpy<2, …
incompatible.
সংখ্যারেখাদুই শর্ত
pandas চায়: ───[2.3.3──▶
আপনি চান : ◀──2)
ছেদ        : কিছুই না
দুই পথকোনটির দাম কম
A: pandas 2 + numpy 1.26
   → 3.14-এ wheel নেই,
     build ব্যর্থ
B: পুরোনো কোড NumPy 2-এ,
   numpy<2 শর্ত বাদ
Terminalসত্যিকারের আউটপুট
$ uv lock --check
Resolved 19 packages in 0.73ms
$ uv run check_env.py
numpy         2.5.4 …
  1. চাওয়া। পুরোনো কোড বাঁচাতে কেউ numpy<2 যোগ করতে চাইলেন। অথচ প্রকল্পের pyproject.toml-এ আগে থেকেই আছে pandas>=3.1.0.
  2. Resolver থামল। uv কোনো কিছু না বদলে error দিল, আর pyproject.toml আগের মতোই রইল। মেসেজটি পুরো যুক্তির শিকল লিখে দিয়েছে: pandas 3.1.0 বা নতুন চায় numpy 2.3.3 বা নতুন, আর আপনি চাইছেন 2-এর নিচে।
  3. কারণ পড়া। দুই শর্তকে সংখ্যারেখায় বসালে ছেদ ফাঁকা — এমন কোনো numpy নেই যা একসাথে ২.৩.৩-এর সমান বা বড় এবং ২-এর ছোট। কোনো টুল এটি “জাদু করে” মেলাতে পারবে না; একটি শর্ত বদলাতেই হবে।
  4. দুটি বিকল্প। A: pandas-কেও পুরোনো করা। কিন্তু Python 3.14-এ numpy 1.26-এর wheel নেই, তাই অংশ ৬-এর মতো build ব্যর্থ হবে — পুরোনো Python-এ নামতে হবে। B: পুরোনো কোডটি NumPy 2-এর উপযোগী করা (যেমন সরানো alias np.float-এর জায়গায় float), তারপর শর্তটি বাদ। এখানে B-এর খরচ কম।
  5. মীমাংসা যাচাই। শর্ত বাদ দেওয়ার পর uv lock --check জানাল lockfile আর pyproject.toml মিলছে — ১৯টি package, ০.৭৩ মিলিসেকেন্ডে। uv run check_env.py আবার numpy 2.5.4 দেখাল। শেষ কাজ: পুরোনো কোডের ফল আগের ফলের সাথে মিলিয়ে দেখা।

Resolver আসলে কী করে, তা ছোট একটি খেলনা-মডেলে দেখা যায়। নিচের কোডে একটি কাল্পনিক টেবিল: pandas-এর দুটি version, বাজারঘরের ভেতরের পুরোনো একটি library forecast (শুধু numpy 2-এর নিচে চলে), আর numpy-র তিনটি version. কৌশল সরল: প্রতিটি package-এর নতুনতম version আগে চেষ্টা, কোনো শর্ত না মিললে পিছিয়ে এসে (backtracking) আগের সিদ্ধান্ত বদলানো। আসল resolver (uv-এর PubGrub-ভিত্তিক, pip-এর resolvelib-ভিত্তিক) এর চেয়ে অনেক চতুর, কিন্তু মূল ধারণা একই। এই পাতার কোড আপনার ব্রাউজারেই চলে; প্রথমবার চালাতে কয়েক সেকেন্ড লাগতে পারে।

# A toy resolver: newest version first, step back on a conflict.
# The table is made up for teaching; real numbers live on PyPI.
INDEX = {
    "pandas":   {"3.1": {"numpy": ("2.3", "99")}, "2.2": {"numpy": ("1.26", "99")}},
    "forecast": {"1.4": {"numpy": ("1.20", "2")}},   # old in-house library
    "numpy":    {"2.5": {}, "2.3": {}, "1.26": {}},
}
V = lambda s: tuple(int(x) for x in s.split("."))     # "1.26" -> (1, 26)

def resolve(todo, chosen, limits):
    if not todo:
        return chosen
    pkg, rest = todo[0], todo[1:]
    lo, hi = limits.get(pkg, ("0", "99"))
    for ver in INDEX[pkg]:                            # newest first
        if not V(lo) <= V(ver) < V(hi):
            print(f"  skip {pkg} {ver}: need {lo} <= {pkg} < {hi}")
            continue
        print(f"  try  {pkg} {ver}")
        new = dict(limits)
        for dep, (dlo, dhi) in INDEX[pkg][ver].items():
            olo, ohi = new.get(dep, ("0", "99"))
            new[dep] = (max(olo, dlo, key=V), min(ohi, dhi, key=V))
        found = resolve(rest, {**chosen, pkg: ver}, new)
        if found:
            return found
    print(f"  back: no {pkg} fits")
    return None

print("result:", resolve(["pandas", "forecast", "numpy"], {}, {}))

আসল আউটপুট:

  try  pandas 3.1
  try  forecast 1.4
  skip numpy 2.5: need 2.3 <= numpy < 2
  skip numpy 2.3: need 2.3 <= numpy < 2
  skip numpy 1.26: need 2.3 <= numpy < 2
  back: no numpy fits
  back: no forecast fits
  try  pandas 2.2
  try  forecast 1.4
  skip numpy 2.5: need 1.26 <= numpy < 2
  skip numpy 2.3: need 1.26 <= numpy < 2
  try  numpy 1.26
result: {'pandas': '2.2', 'forecast': '1.4', 'numpy': '1.26'}

প্রথমে নতুনতম pandas 3.1 নেওয়া হলো, যা চায় numpy ≥ 2.3; তারপর forecast 1.4, যা চায় numpy < 2. দুই শর্ত মিলে সীমা দাঁড়াল 2.3 <= numpy < 2 — অসম্ভব, তাই numpy-র তিনটি version-ই বাদ। Resolver পিছিয়ে এলো: forecast-এর আর কোনো version নেই, তাই আরও পেছনে গিয়ে pandas 2.2. এবার সীমা 1.26 <= numpy < 2, আর numpy 1.26 মিলে গেল। খেয়াল করুন, ফলটা যৌক্তিক হলেও বাস্তবে Python 3.14-এ numpy 1.26-এর wheel নেই — খেলনা resolver wheel দেখে না, আসল resolver দেখে। আর version তুলনা করতে V() লেখাকে সংখ্যার tuple বানায়, যাতে "1.26" আর "1.3"-এর তুলনা ঠিক হয় (লেখা হিসেবে তুলনা করলে ভুল হতো)।

এবার উল্টো দিক থেকে: যে package এই পাতায় নেই, তা import করতে চাইলে কী হয়, আর কীভাবে সেটি ভদ্রভাবে সামলাবেন। নিচের কোড import_module দিয়ে নাম ধরে import চেষ্টা করে, ModuleNotFoundError ধরে, আর বানান ভুল হলে কাছাকাছি নাম প্রস্তাব করে।

import difflib
import importlib
import numpy  # bundled in this page, loaded on purpose

KNOWN = ["numpy", "pandas", "sklearn", "matplotlib", "scipy"]

def try_import(name):
    try:
        mod = importlib.import_module(name)
        print(f"OK    {name:10} {getattr(mod, '__version__', '?')}")
    except ModuleNotFoundError as err:
        print(f"MISS  {name:10} {err}")
        close = difflib.get_close_matches(name, KNOWN, n=1)
        if close:
            print(f"      did you mean '{close[0]}'?")
        else:
            print("      not in this page; install it on your own computer")

for name in ["numpy", "torch", "tensorflow", "pandsa"]:
    try_import(name)

আসল আউটপুট:

OK    numpy      2.4.6
MISS  torch      No module named 'torch'
      not in this page; install it on your own computer
MISS  tensorflow No module named 'tensorflow'
      not in this page; install it on your own computer
MISS  pandsa     No module named 'pandsa'
      did you mean 'pandas'?

numpy পাওয়া গেল — তবে version 2.4.6, আপনার কম্পিউটারের 2.5.4 নয়; কারণটা অংশ ৮-এ। torch আর tensorflow এই পাতার Python-এ নেই, তাই ModuleNotFoundError; কোড থামেনি, কারণ except সেটি ধরে একটি বোধগম্য বার্তা দিয়েছে। শেষেরটি একটি টাইপো: difflib.get_close_matches জানা নামের তালিকা থেকে সবচেয়ে কাছের pandas প্রস্তাব করেছে। বাস্তব প্রকল্পে এমন ঐচ্ছিক import ধরার অভ্যাস কাজে লাগে, কিন্তু দরকারি package না থাকলে চুপ না থেকে স্পষ্ট বার্তা দিয়ে থেমে যাওয়াই ভালো।

৮ · এই কোর্সের পাতায় Python — Pyodide কী পারে, কী পারে না

এই কোর্সের “চালান” বোতাম চাপলে কোড কোনো সার্ভারে যায় না, চলে আপনার ব্রাউজারেই। এর পেছনে আছে Pyodide: আসল CPython interpreter, যাকে WebAssembly-তে compile করা হয়েছে, আর তার সাথে NumPy, pandas, scikit-learn, matplotlib-এর মতো package, যেগুলোও ব্রাউজারের জন্য আলাদা করে build করা। Pyodide শুরু হয়েছিল ২০১৮ সালের দিকে Mozilla-তে (Michael Droettboom-এর নেতৃত্বে), পরে এটি একটি স্বাধীন open-source প্রকল্প হয়।

ভাবুন একটি ভ্রাম্যমাণ লাইব্রেরি-বাসের কথা। আসল বই, আসল পাঠাগারিক — কিন্তু বাসে যতটুকু জায়গা, ততটুকু বই। কোনো বই না থাকলে বাসে বসে অর্ডার দেওয়া যায় না। Pyodide-ও আসল Python, কিন্তু ব্রাউজারের সীমার ভেতরে, আর আগে থেকে সাজানো package নিয়ে।

প্রথম ব্লকটি দেখায় এই পাতায় কোন version-গুলো আছে। লক্ষ করুন, importlib.metadata-এ নাম scikit-learn, আর import-এ sklearn. scikit-learn প্রথমবার লোড হতে প্রায় ১০ সেকেন্ড লাগতে পারে।

import sys
from importlib.metadata import version

# importing makes the page load these packages
import numpy, pandas, sklearn, matplotlib

print("Python", sys.version.split()[0])
for dist in ["numpy", "pandas", "scikit-learn", "matplotlib"]:
    print(f"{dist:13} {version(dist)}")

# the module's own attribute says the same thing
print("sklearn.__version__ =", sklearn.__version__)
print("numpy.__version__   =", numpy.__version__)

আসল আউটপুট:

Python 3.14.2
numpy         2.4.6
pandas        3.0.2
scikit-learn  1.8.0
matplotlib    3.10.8
sklearn.__version__ = 1.8.0
numpy.__version__   = 2.4.6

পাতার Python 3.14.2, আর package-গুলো আপনার কম্পিউটারের চেয়ে কিছুটা পুরোনো: numpy 2.4.6 বনাম 2.5.4, scikit-learn 1.8.0 বনাম 1.9.1. কারণ Pyodide-এর প্রতিটি প্রকাশ একটি নির্দিষ্ট সময়ের package-সেট আলাদা করে build করে বাঁধে — নিজেই একরকম lockfile. এই কোর্সের কোড দুই জায়গাতেই চলার মতো করে লেখা, তবে কোনো আচরণ version-ভেদে আলাদা হলে পাতায় তা বলা থাকবে। দুই উপায়ে পড়া version একই — importlib.metadata ইনস্টল-তথ্য থেকে, __version__ module-এর ভেতর থেকে।

দ্বিতীয় ব্লক দেখায় এই Python নিজেকে কোথায় চলছে বলে মনে করে। (কম্পিউটারের নাম, ফোল্ডার বা অন্য কোনো ব্যক্তিগত তথ্য ইচ্ছে করেই ছাপা হচ্ছে না।)

import sys

print("sys.version :", sys.version)
print("sys.platform:", sys.platform)

major, minor = sys.version_info[:2]
print("version_info:", (major, minor))

if sys.platform == "emscripten":
    print("Running inside the browser (WebAssembly).")
    print("No terminal, no pip/uv, no subprocess, no GPU here.")
else:
    print("Running as a normal program on a computer.")

আসল আউটপুট (প্রথম লাইনের লম্বা শেষাংশ ছাঁটা):

sys.version : 3.14.2 (main, Sep 14 2026, 03:03:51) [Clang 23.0.0git (…llvm-project e5927fecf8a6…
sys.platform: emscripten
version_info: (3, 14)
Running inside the browser (WebAssembly).
No terminal, no pip/uv, no subprocess, no GPU here.

sys.version শুধু version নম্বর নয়, এই interpreter কবে আর কোন compiler দিয়ে build হয়েছে তাও বলে — এখানে Clang, যা WebAssembly-র জন্য build করতে ব্যবহৃত হয়। শুধু নম্বর চাইলে sys.version_info নিরাপদ, কারণ সেটি সংখ্যার tuple, তুলনা করা যায়। sys.platform-এর মান emscripten — WebAssembly-তে C/C++ compile করার টুলচেইনের নাম। আপনার কম্পিউটারে একই কোড চালালে Windows-এ win32, Linux-এ linux, macOS-এ darwin পাবেন। কোড যদি কোথায় চলছে তার ওপর আচরণ বদলাতে চায়, এই মানটি দেখেই সিদ্ধান্ত নেয়।

এই পাতায় চলেএই পাতায় চলে না
সাধারণ Python, standard library-র বেশিরভাগterminal, pip, uv, subprocess
পাতায় আগে থেকে থাকা NumPy, pandas, scikit-learn, matplotlib, SciPy, statsmodels; প্রয়োজনে seabornঅন্য যেকোনো package নামানো (torch, tensorflow, Polars ইত্যাদি)
পাতায় রাখা ছোট ডেটা-ফাইল পড়া; ব্রাউজারের ভেতরের অস্থায়ী ফাইলআপনার কম্পিউটারের ফাইল, ইন্টারনেট থেকে ডেটা আনা
ছোট, দ্রুত শেষ হওয়া হিসাববড় model শেখানো, GPU, অনেকক্ষণ চলা loop (পাতা আটকে যায়)

সাধারণ Pyodide-এ micropip নামে একটি ছোট ইনস্টলার দিয়ে কিছু pure-Python package নামানো যায়, কিন্তু এই কোর্সের পাতা ইচ্ছে করেই তা বন্ধ রাখে, যাতে সব পাঠক একই পরিবেশ পান আর পাতা নিরাপদ থাকে। শেখার জন্য পাতা, আর আসল প্রকল্পের জন্য নিজের কম্পিউটারে uv — দুটোই দরকার। পরের পর্বে (পর্ব ৮, Jupyter notebook) দেখবেন একই uv প্রকল্পের ভেতরে কীভাবে notebook চালানো হয়।

আরও গভীরে: import-এর নাম থেকে distribution-এর নাম খুঁজতে importlib.metadata.packages_distributions() আছে; installed package-এর তথ্য থাকে প্রতিটি package-এর .dist-info ফোল্ডারে (মানক: PEP 376 ও পরবর্তী core metadata স্পেসিফিকেশন)। uv-এর resolver PubGrub অ্যালগরিদমের ওপর দাঁড়ানো, যা Dart ভাষার package manager-এর জন্য Natalie Weizenbaum ২০১৮ সালে বর্ণনা করেন; এর বিশেষত্ব হলো ব্যর্থ হলে মানুষ-পড়ার মতো কারণ-শিকল লেখা, যা আপনি ধাপ ২-এর error-এ দেখেছেন। আর wheel tag-এর পূর্ণ নিয়ম PEP 425-এ, Linux-এর manylinux নিয়ম PEP 600-এ।

পরীক্ষা ও ইন্টারভিউতে (বিশ্ববিদ্যালয়, চাকরি বা ইন্টারভিউর পরীক্ষায় যে ধরনের প্রশ্ন সাধারণত আসে):

  • Virtual environment কেন? — প্রতিটি প্রকল্পের package আলাদা রাখতে, যাতে এক প্রকল্পের version অন্যটিকে না ভাঙে।
  • pip install করার পরও ModuleNotFoundError — কেন? — package গেছে অন্য Python বা অন্য venv-এ; python -m pip বা uv run ব্যবহার করুন।
  • requirements.txt আর lockfile-এর পার্থক্য? — প্রথমটি নাম-version-এর তালিকা; lockfile-এ transitive dependency, উৎস, hash আর (uv-তে) সব OS-এর তথ্য থাকে।
  • wheel আর sdist? — wheel আগে থেকে build করা, সাথে সাথে বসে; sdist সোর্স, compile করতে হয়।
  • conda কখন pip-এর চেয়ে ভালো? — যখন Python-এর বাইরের library (C/C++, CUDA, GDAL) লাগে, যার wheel নেই বা ঝামেলার।

৯ · AI-এর যুগে — AI সহকারীর ইনস্টল-পরামর্শ যাচাই

সেটআপে আটকে গেলে AI সহকারী দ্রুত সাহায্য করে। কিন্তু ইনস্টল আর version-এর প্রশ্নে তার ভুলের ধরনগুলো চেনা দরকার, কারণ এখানে তথ্য খুব দ্রুত পুরোনো হয় — AI যে ডেটায় শিখেছে, তার পরে নতুন Python, নতুন NumPy, নতুন uv এসে গেছে। ডেটা আর AI-এর কাজে AI সহকারী প্রায়ই যে ভুল করে:

AI সহকারীর ভুলকীভাবে ধরবেন
pip install sklearn, বা পুরোনো Python version-এর পরামর্শPyPI-তে আসল নাম আর সমর্থিত Python দেখা; চালিয়ে error পড়া
পুরোনো API — pandas-এর DataFrame.append, NumPy-র np.floatনিজের version-এর অফিসিয়াল docs; uv run দিয়ে চালিয়ে দেখা
অস্তিত্বহীন কমান্ড বা flag বানানো (যেমন uv-এর পুরোনো বা কাল্পনিক option)uv … --help আর docs.astral.sh/uv মিলিয়ে দেখা
conflict চাপা দিতে --force-reinstall, --no-deps বা sudo দিয়ে সিস্টেম Python-এ ইনস্টলerror-এর কারণ-শিকল পড়ে কোন শর্ত বদলাতে হবে তা বোঝা
warning লুকানো (warnings.filterwarnings("ignore"))warning পড়ে কারণ বোঝা — প্রায়ই সেটি আসন্ন version-বদলের খবর
ডেটার কাজে: split-এর আগে পুরো ডেটায় scaling, training set-এ metric দেখানো, বিশ্বাসযোগ্য কিন্তু ভুল পরিসংখ্যানআগে split (পর্ব ৫৬), সহজ baseline-এর সাথে তুলনা, হাতে একটি সংখ্যা মেলানো

AI সহকারীকে সেটআপের প্রশ্ন করার সময় নিজের আসল অবস্থা জানান, আর তাকে অনিশ্চয়তা স্বীকার করতে বলুন। কোনো ব্যক্তিগত ফোল্ডারের নাম বা টোকেন পেস্ট করবেন না:

আমি Windows-এ uv 0.13.7 আর Python 3.14 দিয়ে একটি ডেটা-বিশ্লেষণ প্রকল্প চালাচ্ছি (numpy, pandas, scikit-learn, matplotlib). এখন একটি পুরোনো কোড যোগ করতে গিয়ে uv add "numpy<2" চালালে এই error এসেছে: [এখানে পুরো error মেসেজ, ফোল্ডারের নাম সরিয়ে] ১. error-এর কারণ-শিকলটি সহজ বাংলায় ভেঙে বলো। ২. সম্ভাব্য সমাধানগুলোর তালিকা দাও, প্রতিটির খরচ আর ঝুঁকিসহ। --no-deps বা --force জাতীয় চাপা দেওয়ার পথ দিও না। ৩. কোনো uv কমান্ড বা option বললে সেটি docs.astral.sh/uv-এর কোন পাতায় আছে বলো। ৪. যেখানে তুমি নিশ্চিত নও বা তোমার তথ্য পুরোনো হতে পারে, সেখানে স্পষ্ট করে লেখো।

AI সহকারীর সেটআপ-পরামর্শ হাতে পেলে — যাচাইয়ের চেকলিস্ট

ভাবনার প্রশ্ন

প্রতিটি প্রশ্ন নিয়ে নিজে কিছুক্ষণ ভাবুন — তারপর “→ উত্তর” চাপুন।

প্র ০১NumPy কেন পুরো AI-এর Python জগতের ভিত্তি হয়ে উঠল, আর NumPy 2.0-এর মতো বড় বদল কেন পুরো জগৎকে নাড়া দেয়?

১৯৯০-এর দশকে Python-এ সংখ্যার array নিয়ে কাজের জন্য Numeric নামে একটি library ছিল। পরে বড় array-র জন্য আরেকটি library, Numarray, তৈরি হয়। দুটি আলাদা library থাকায় বিজ্ঞানের Python সম্প্রদায় ভাগ হয়ে গিয়েছিল — কোনো library এক ধরনের array নিত, কোনোটি আরেক ধরনের। Travis Oliphant দুটির ভালো দিক মিলিয়ে NumPy বানান, আর ২০০৬ সালে NumPy 1.0 প্রকাশিত হয়। এর পর থেকে প্রায় সব নতুন library একটিই “সাধারণ ভাষা” ব্যবহার করতে শুরু করে: ndarray. ২০২০ সালে Harris ও সহকর্মীরা Nature পত্রিকায় “Array programming with NumPy” প্রবন্ধে এই ইতিহাস আর নকশা বর্ণনা করেন।

এই সাধারণ ভাষার শক্তি বিশাল। pandas-এর প্রতিটি কলাম ভেতরে মূলত NumPy array (যদিও নতুন pandas-এ অন্য ধরনের কলামও আছে), scikit-learn ইনপুট হিসেবে NumPy array নেয়, matplotlib NumPy array আঁকে। ফলে একটি library-র আউটপুট সরাসরি আরেকটির ইনপুট হয়, কোনো রূপান্তর লাগে না। এর মূলে আছে NumPy-র memory-বিন্যাস আর C-ইন্টারফেস, যার ওপর অন্যরা নিজেদের compile করা কোড বসায়।

ঠিক এই কারণেই NumPy-র বড় বদল ঝাঁকুনি দেয়। ২০২৪ সালের মাঝামাঝি NumPy 2.0 এসেছিল প্রায় দেড় দশকের মধ্যে প্রথম বড় ভাঙনসহ: পুরোনো কিছু alias বাদ, কিছু type-নিয়ম বদল, আর C-স্তরে ABI বদল। NumPy 1.x-এর বিরুদ্ধে compile করা অনেক পুরোনো package NumPy 2-এর সাথে চালাতে গেলে ভেঙে যায়, তাই ওপরের প্রায় সব library-কে নতুন করে build করে প্রকাশ করতে হয়েছিল। NumPy দল আগে থেকে সতর্ক করে, পরিবর্তনের নির্দেশিকা লিখে আর অন্য প্রকল্পের সাথে সমন্বয় করে এই বদল সামলানোর চেষ্টা করে; তবু কয়েক মাস ধরে অনেক প্রকল্পে “numpy<2” ধরনের অস্থায়ী শর্ত দেখা গেছে। এই পর্বের version conflict-এর উদাহরণ সেই অভিজ্ঞতারই ছোট রূপ।

মূল উপলব্ধি: একটি সাধারণ ভিত্তি পুরো জগৎকে জুড়ে দেয়, আবার সেই ভিত্তি বদলালে পুরো জগৎ একসাথে নড়ে। তাই ভিত্তি-library-র version সচেতনভাবে বাছুন, আর lockfile দিয়ে বেঁধে রাখুন।

প্র ০২শুধু requirements.txt দিয়ে কাজ চালালে ক্ষতি কী? lockfile-এর ধারণা কীভাবে এলো, আর library আর application-এর জন্য নিয়ম কেন আলাদা?

requirements.txt কোনো মানক ফরম্যাট নয়, pip-এর একটি প্রথা। এতে দুই রকম তালিকা রাখা যায়, আর সমস্যা হয় দুটি গুলিয়ে ফেললে। একটি হলো “আমার কী লাগে” (pandas>=3), আরেকটি হলো “এই মুহূর্তে কী বসানো আছে” (pip freeze-এর আউটপুট)। প্রথমটি থেকে ছয় মাস পরে ইনস্টল করলে নতুন version আসবে, ফল বদলাতে পারে। দ্বিতীয়টিতে সব হুবহু, কিন্তু কোনটি আপনি চেয়েছিলেন আর কোনটি সাথে এসেছে তা হারিয়ে যায়, ফাইলের hash থাকে না, আর একটি OS-এর জন্য তৈরি তালিকা অন্য OS-এ নাও মিলতে পারে (কিছু package শুধু Windows-এ লাগে, কিছু শুধু Linux-এ)।

এই সমস্যার সমাধান অন্য ভাষার জগতে আগেই এসেছিল — Ruby-র Bundler-এর Gemfile.lock, JavaScript-এর package-lock.json. Python-এ pip-tools (pip-compile) একটি “চাওয়া” ফাইল থেকে পূর্ণ “পিন করা” ফাইল বানানোর পথ দেখায়। ২০১৭–১৮ সালের দিকে Pipenv আর Poetry নিজস্ব lockfile আনে। তারপর uv-এর uv.lock, যা cross-platform. অনেক বছর ধরে Python-এ কোনো মানক lockfile ছিল না; সম্প্রদায়ের দীর্ঘ আলোচনার পর ২০২৫ সালে PEP 751 গৃহীত হয়, যা pylock.toml ফরম্যাট নির্ধারণ করে। কোন টুল কতটা এটি গ্রহণ করবে, তা সময় বলবে।

library আর application-এর পার্থক্যও জরুরি। আপনি যদি অন্যের ব্যবহারের জন্য একটি library লেখেন, তাহলে pyproject.toml-এ সীমা ঢিলেঢালা রাখাই ভালো (numpy>=2), যাতে ব্যবহারকারী নিজের প্রকল্পে অন্য library-র সাথে মেলাতে পারেন; library-র lockfile ব্যবহারকারী পান না। কিন্তু আপনার application বা বিশ্লেষণ-প্রকল্প — যেমন বাজারঘরের রিপোর্ট — হুবহু পুনরুৎপাদন চায়, তাই সেখানে lockfile রাখা আবশ্যক। AI প্রকল্পে এটি আরও গুরুত্বপূর্ণ, কারণ scikit-learn বা NumPy-র ছোট বদলেও ডিফল্ট parameter বা random সংখ্যার ধারা বদলে model-এর ফল বদলাতে পারে।

মূল উপলব্ধি: “কী চাই” আর “কী বসেছে” দুটি আলাদা দলিল। প্রথমটি pyproject.toml-এ, দ্বিতীয়টি lockfile-এ — দুটোই রাখুন।

প্র ০৩conda আর pip/uv — দুটি আলাদা জগৎ কেন তৈরি হলো? আজ wheel থাকার পরও conda-র জায়গা কোথায়?

২০১০-এর দশকের শুরুতে বিজ্ঞানের Python বসানো ছিল বড় ঝামেলা, বিশেষ করে Windows-এ। NumPy আর SciPy-র জন্য C আর Fortran compiler লাগত, BLAS/LAPACK-এর মতো সংখ্যা-গণনার library লাগত, আর সেগুলো Windows-এ সহজে পাওয়া যেত না। তখন pip সাধারণত শুধু সোর্স নামাত। এই প্রেক্ষাপটে ২০১২ সালে Continuum Analytics (পরে Anaconda) conda আনে, যার নকশা ভিন্ন: package মানে শুধু Python কোড নয়, যেকোনো compile করা ফাইলের বান্ডিল — C library, compiler, এমনকি Python নিজেও। ফলে conda দিয়ে একটি কমান্ডে পুরো বিজ্ঞানের stack বসানো যেত, যা তখন বিপ্লবের মতো ছিল। ডেটা সায়েন্স শিক্ষায় Anaconda distribution অনেক বছর প্রায় ডিফল্ট ছিল।

একই সময়ে PyPI-জগৎও এগোয়। ২০১২–১৩ সালে wheel ফরম্যাট (PEP 427) আসে, ২০১৬ সালে manylinux (PEP 513) Linux-এর জন্য একটি সাধারণ binary মান দেয়, আর বড় প্রকল্পগুলো স্বয়ংক্রিয় build-ব্যবস্থায় প্রতিটি OS ও Python-এর wheel বানাতে শুরু করে। NumPy-র wheel-এর ভেতরেই এখন OpenBLAS-এর মতো library জুড়ে দেওয়া থাকে। ফলে আজ এই কোর্সের পুরো stack pip বা uv দিয়েই কয়েক সেকেন্ডে বসে।

তবু conda-র জায়গা আছে, যেখানে Python-এর বাইরের নির্ভরতা জটিল: ভূগোলের GDAL/PROJ, bioinformatics-এর টুল, কিছু GPU stack, অথবা একই পরিবেশে R আর Python. conda-forge-এর মতো সম্প্রদায়-চালিত channel হাজার হাজার এমন package রক্ষণাবেক্ষণ করে। দুর্বলতাও আছে: দুই জগৎ মেশালে বিভ্রান্তি, package-এর version কখনো PyPI-র চেয়ে পিছিয়ে, আর আগে solver ধীর ছিল — mamba ঠিক এই সমস্যা মেটাতে এসেছিল, পরে conda নিজেও libmamba solver গ্রহণ করে। নতুন টুলও আসছে (যেমন pixi), যা conda-র package আর আধুনিক lockfile মেলাতে চায়। কোনটি “সেরা” — এ নিয়ে সম্প্রদায়ে মতভেদ আছে; প্রশ্নটা আসলে আপনার package-গুলো কোথায় ভালোভাবে পাওয়া যায়।

মূল উপলব্ধি: conda আর pip একই সমস্যার দুটি সমাধান — ভিন্ন সময়ে, ভিন্ন সীমাবদ্ধতায় জন্ম। আপনার প্রকল্পের dependency-গুলো দেখে টুল বাছুন, অভ্যাস দেখে নয়।

প্র ০৪ব্রাউজারে আসল Python চালানো (Pyodide) শেখার জন্য কতটা ভালো? এর সুবিধা আর ঝুঁকি কী?

WebAssembly ২০১৭ সালের দিকে প্রধান ব্রাউজারগুলোতে আসে — এটি এমন একটি নিম্নস্তরের ফরম্যাট, যাতে C/C++-এর মতো ভাষার কোড compile করে ব্রাউজারে প্রায়-নেটিভ গতিতে চালানো যায়। Emscripten টুলচেইন দিয়ে CPython-কে WebAssembly-তে compile করার পরীক্ষা আগেও ছিল, কিন্তু Pyodide (২০১৮ সালে Mozilla-তে শুরু) বড় পদক্ষেপ নেয়: শুধু Python নয়, NumPy, pandas, SciPy, matplotlib-এর মতো compile করা package-ও ব্রাউজারের জন্য build করে। পরে প্রকল্পটি Mozilla থেকে আলাদা হয়ে সম্প্রদায়-চালিত হয়। JupyterLite-এর মতো প্রকল্প এর ওপর পুরো notebook ব্রাউজারে চালায়, আর PyScript একে ওয়েবপাতায় জুড়ে দেয়।

শেখার জন্য সুবিধা স্পষ্ট। কিছু ইনস্টল না করেই পাঠক আসল কোড চালাতে পারেন — বাংলাদেশে অনেকেই ফোন বা পুরোনো কম্পিউটার থেকে শেখেন, তাঁদের জন্য এটি বড় দরজা। কোড চলে পাঠকের নিজের ব্রাউজারে, সার্ভারে নয়, তাই কোনো সার্ভারে অচেনা কোড চালানোর নিরাপত্তা-ঝুঁকি নেই; ব্রাউজারের sandbox কোডকে কম্পিউটারের ফাইলে হাত দিতে দেয় না। আর সবাই একই version পান, তাই ফলও মেলে।

সীমাও আছে, আর সেগুলো সৎভাবে বলা দরকার। প্রথমবার package নামাতে সময় লাগে, ধীর ইন্টারনেটে বেশি। ব্রাউজারের memory সীমিত, বড় ডেটা বা বড় model চলে না। threads আর subprocess প্রায় নেই, GPU নেই। package-এর version আপনার কম্পিউটারের চেয়ে পিছিয়ে থাকতে পারে, যেমন এই পাতায় numpy 2.4.6. সবচেয়ে বড় শিক্ষাগত ঝুঁকি হলো, পাঠক ভেবে বসতে পারেন “সেটআপ তো কোনো ব্যাপার না” — অথচ চাকরির জীবনে প্রথম সপ্তাহের কাজই প্রায়ই পরিবেশ ঠিক করা। এজন্য এই কোর্স দুটো একসাথে রাখে: ধারণা পরীক্ষার জন্য পাতা, আর আসল কাজের জন্য uv-প্রকল্পের সত্যিকারের run.

মূল উপলব্ধি: ব্রাউজারের Python শেখার বাধা কমায়, কিন্তু আসল পরিবেশের বিকল্প নয়। যে কোড পাতায় চলে, তা নিজের কম্পিউটারেও একবার চালিয়ে দেখুন।

প্র ০৫uv-এর মতো দ্রুত, Rust-এ লেখা, একটি কোম্পানির তৈরি টুলের ওপর নির্ভর করা কতটা নিরাপদ সিদ্ধান্ত?

গত কয়েক বছরে Python-এর অনেক জনপ্রিয় নতুন টুল এসেছে Rust-এ লেখা হয়ে: Ruff (২০২২, linter), uv (২০২৪), Polars (DataFrame library, পর্ব ২৭-এ পরিচয়)। এদের বড় আকর্ষণ গতি। এই পর্বের একটি local run-এই দেখা গেছে, cache ভরা অবস্থায় একই ১৮টি package নতুন পরিবেশে বসাতে pip-এর লেগেছে ১৮.৭ সেকেন্ড, uv-এর ১.৩ সেকেন্ড। একজনের ল্যাপটপে এটি সামান্য, কিন্তু যে দল দিনে শত শত বার CI-তে পরিবেশ বানায়, তাদের কাছে বড়।

প্রশ্ন ওঠে নির্ভরতা নিয়ে। uv তৈরি করে Astral নামের একটি venture-অর্থায়িত কোম্পানি; টুলটি open source (MIT/Apache লাইসেন্স), কিন্তু ভবিষ্যতে কোম্পানির ব্যবসায়িক সিদ্ধান্ত কী হবে, তা কেউ নিশ্চিত বলতে পারে না। ইতিহাসে বহু open-source টুল দেখা গেছে, যার রক্ষণাবেক্ষণকারী বদলেছে বা লাইসেন্স বদলেছে। আবার pip-এর মতো সম্প্রদায়-চালিত টুলের রক্ষণাবেক্ষণও হয় কয়েকজন স্বেচ্ছাসেবীর সীমিত সময়ে — সেখানেও নিজস্ব ঝুঁকি আছে।

ঝুঁকি কমানোর সবচেয়ে ভালো উপায় হলো মানকের ওপর দাঁড়ানো। uv-প্রকল্পের মূল তথ্য থাকে pyproject.toml-এ, যার ফরম্যাট PEP 621-এ নির্ধারিত, আর যেকোনো আধুনিক টুল তা পড়তে পারে। package আসে PyPI থেকে, মানক wheel আকারে। lockfile export করা যায় requirements.txt বা PEP 751-এর pylock.toml-এ। অর্থাৎ কাল uv বাদ দিতে হলেও আপনার প্রকল্প venv আর pip দিয়ে চালানো যাবে — এই পর্বের অংশ ৫ ঠিক সেটিই দেখিয়েছে। আর নতুন টুল এলে পুরোনো টুলও উন্নত হয়; প্রতিযোগিতা সাধারণত পুরো জগতের জন্য ভালো।

মূল উপলব্ধি: টুল বদলায়, মানক টিকে থাকে। যে টুলই নিন, প্রকল্পের তথ্য মানক ফাইলে রাখুন, আর অন্তত একটি বিকল্প পথে চালাতে জানুন।

অনুশীলন

হিসাব, আগাম অনুমান, কোড আর নকশা-সমালোচনা — চার রকম কাজ।

  1. হিসাব করুন: একটি local run-এ একই ১৮টি package বসাতে সময় লেগেছে — cache খালি: pip ৮৫.৯ সেকেন্ড, uv ৪৩.৯ সেকেন্ড; cache ভরা: pip ১৮.৭ সেকেন্ড, uv ১.৩ সেকেন্ড। দুই অবস্থায় uv কত গুণ দ্রুত? একটি দল দিনে ৪০ বার cache-ভরা অবস্থায় পরিবেশ বানালে দিনে কত মিনিট বাঁচে? cache-খালি অবস্থার অনুপাত নিয়ে কেন বেশি সতর্ক থাকা উচিত?

    cache খালি: ৮৫.৯ ÷ ৪৩.৯ ≈ ১.৯৬, অর্থাৎ প্রায় ২ গুণ। cache ভরা: ১৮.৭ ÷ ১.৩ ≈ ১৪.৪, অর্থাৎ প্রায় ১৪ গুণ।

    প্রতিবার বাঁচে ১৮.৭ − ১.৩ = ১৭.৪ সেকেন্ড; ৪০ বারে ১৭.৪ × ৪০ = ৬৯৬ সেকেন্ড ≈ ১১.৬ মিনিট।

    cache-খালি অবস্থায় সময়ের বড় অংশ ইন্টারনেটে প্রায় ৮৪ MiB ফাইল নামানো (uv-এর run-এ “Prepared 19 packages in 41.69s”). দুটি run আলাদা সময়ে হয়েছিল, নেটওয়ার্কের গতি তখন একই ছিল কি না জানা নেই। তাই সেই ২ গুণের অনেকটা টুলের নয়, নেটওয়ার্কের পার্থক্যও হতে পারে। ভালো তুলনার জন্য একই সময়ে কয়েকবার চালিয়ে গড় আর ছড়ানো দেখতে হয় — আর তখনও সেটি শুধু ওই কম্পিউটার আর নেটওয়ার্কের ফল।

  2. আগাম বলুন (predict the output): খেলনা resolver-এর টেবিলে forecast-এর একটি নতুন version যোগ করা হলো, যা numpy 3-এর নিচে সব চালায়: "forecast": {"1.5": {"numpy": ("1.20", "3")}, "1.4": {"numpy": ("1.20", "2")}} (1.5 আগে, কারণ নতুনতম আগে)। চালানোর আগে লিখে ফেলুন কী কী লাইন ছাপা হবে, তারপর উপরের কোড-বাক্সে বদলে মিলিয়ে নিন।

    pandas 3.1 নিলে numpy-র সীমা হয় ২.৩ থেকে ৯৯; forecast 1.5 যোগ করলে সীমা ২.৩ থেকে ৩। নতুনতম numpy 2.5 এই সীমায় পড়ে, তাই কোনো পিছিয়ে আসা লাগে না:

      try  pandas 3.1
      try  forecast 1.5
      try  numpy 2.5
    result: {'pandas': '3.1', 'forecast': '1.5', 'numpy': '2.5'}

    এটি একটি local run-এ মিলিয়ে দেখা হয়েছে। শিক্ষা: অনেক conflict-এর আসল সমাধান হলো পুরোনো dependency-র নতুন version (বা নিজের কোড হালনাগাদ), বাকি সবকিছু পুরোনো করা নয়।

  3. কোড লিখুন: একটি স্ক্রিপ্ট লিখুন যা একটি dict-এ রাখা ন্যূনতম version (numpy 2.0, pandas 3.0, scikit-learn 1.8, seaborn 0.13) মিলিয়ে প্রতিটির জন্য OK, OLD বা MISSING ছাপবে। শুধু standard library ব্যবহার করুন, আর কোনো package import না করে version পড়ুন।
    from importlib.metadata import version, PackageNotFoundError
    
    NEED = {"numpy": "2.0", "pandas": "3.0", "scikit-learn": "1.8", "seaborn": "0.13"}
    
    def as_tuple(v):
        return tuple(int(p) for p in v.split(".")[:2])
    
    for pkg, low in NEED.items():
        try:
            have = version(pkg)
        except PackageNotFoundError:
            print(f"MISSING {pkg} (need >= {low})")
            continue
        status = "OK " if as_tuple(have) >= as_tuple(low) else "OLD"
        print(f"{status}     {pkg} {have} (need >= {low})")

    বাজারঘরের uv-প্রকল্পে uv run min_versions.py-এর সত্যিকারের আউটপুট:

    OK      numpy 2.5.4 (need >= 2.0)
    OK      pandas 3.1.0 (need >= 3.0)
    OK      scikit-learn 1.9.1 (need >= 1.8)
    MISSING seaborn (need >= 0.13)

    প্রথম দুই অংশ নিয়ে tuple বানানো হয়েছে, যাতে "3.11" আর "3.9"-এর তুলনা সংখ্যা হিসেবে হয়। বাস্তবে 2.0rc1 বা 1.0.post1-এর মতো version-ও থাকে; তখন packaging.version.Version ব্যবহার করাই নিরাপদ (সেটি আলাদা package, যদিও প্রায় সব পরিবেশে থাকে)।

  4. নকশা-সমালোচনা: একটি কাল্পনিক দলের README-তে লেখা: “Python-এর সর্বশেষ version নিন। তারপর sudo pip install numpy pandas sklearn tensorflow চালান। কোড চলবে।” এই নির্দেশে কোন কোন সমস্যা দেখছেন, আর আপনি নির্দেশটি কীভাবে লিখবেন?
    • “সর্বশেষ version”: সময়ের সাথে অর্থ বদলায়। লেখার সময়ে সর্বশেষ 3.15-এর জন্য TensorFlow 2.21.0-এর wheel ছিল না (শুধু cp310–cp313). নির্দিষ্ট version লিখুন, যেমন requires-python আর .python-version-এ।
    • sudo pip: সিস্টেম Python-এ package বসায়, অপারেটিং সিস্টেমের নিজের টুল ভাঙতে পারে; অনেক Linux-এ externally-managed-environment দিয়ে আটকেও যায়। প্রকল্পের venv বা uv ব্যবহার করুন।
    • sklearn: ভুল নাম; PyPI-র sklearn ইচ্ছাকৃতভাবে ইনস্টলে error দেয়। ঠিক নাম scikit-learn.
    • কোনো version বা lockfile নেই: ছয় মাস পরে অন্য version আসবে, ফল বদলাতে পারে। pyproject.toml আর uv.lock রাখুন।
    • যাচাই নেই: “কোড চলবে” নয়, একটি যাচাই-কমান্ড দিন যা version ছাপে।

    ভালো নির্দেশ: “uv ইনস্টল করুন। প্রকল্পের ফোল্ডারে uv sync --locked, তারপর uv run check_env.py চালিয়ে দেখুন version-গুলো README-র তালিকার সাথে মেলে কি না। TensorFlow লাগলে আলাদা পরিবেশে, তার সমর্থিত Python version-এ।”

নিজেকে যাচাই করুন

ভুল হলে কারণসহ ব্যাখ্যা পাবেন, আবার চেষ্টাও করতে পারবেন।

ক্রমuv দিয়ে একটি নতুন AI প্রকল্প শুরুর ধাপগুলো সঠিক ক্রমে সাজান (▲▼ চেপে সরান)

  1. 🐍 uv python install 3.14 — দরকারি Python নামানো
  2. 📁 uv init bazarghar-ai — প্রকল্পের কাঠামো
  3. ➕ uv add numpy pandas scikit-learn matplotlib — resolve, lock, install
  4. ▶️ uv run check_env.py — চালিয়ে version যাচাই
  5. 🗂️ pyproject.toml আর uv.lock একসাথে সংরক্ষণ, অন্যত্র uv sync --locked

একটি ফাইলের নাম numpy-2.5.4-cp314-cp314-win_amd64.whl. এটি কোথায় সরাসরি ইনস্টল হবে?

  • যেকোনো Python 3, যেকোনো OS-এ
  • CPython 3.14, ৬৪-বিট Windows-এ
  • CPython 3.14, ৬৪-বিট Linux-এ
  • শুধু Pyodide-এর মতো ব্রাউজার-Python-এ

একজন terminal-এ pip install pandas চালিয়ে “Successfully installed” দেখলেন, কিন্তু python analysis.py চালাতেই এলো ModuleNotFoundError: No module named 'pandas'. সবচেয়ে সম্ভাব্য কারণ কী?

  • pandas-এর ফাইল নষ্ট হয়ে গেছে
  • analysis.py-তে syntax ভুল আছে
  • pip একটি Python-এ বসিয়েছে, আর python চালাচ্ছে আরেকটি Python
  • চালানোর সময় ইন্টারনেট সংযোগ ছিল না

pip freeze > requirements.txt-এর তুলনায় uv-এর uv.lock কোন তথ্য বাড়তি রাখে?

  • ফাইলের hash, কোন package কার কারণে এসেছে, আর অন্য OS-এর ফাইলের তথ্য
  • শুধু প্রতিটি package-এর হুবহু version
  • প্রতিটি package-এর পূর্ণ সোর্স কোড
  • কম্পিউটারের নাম আর ব্যবহারকারীর ফোল্ডার

কোডে import sklearn ঠিকঠাক চলে। তাহলে importlib.metadata.version(...)-এ কোন নাম দিলে scikit-learn-এর version পাওয়া যাবে?

  • "sklearn"
  • "sk_learn"
  • "scikit"
  • "scikit-learn"

uv এই error দিল: “Because pandas>=3.1.0 depends on numpy>=2.3.3 and your project depends on numpy<2, … incompatible.” প্রকল্পে pandas 3 দরকার। সবচেয়ে ভালো পদক্ষেপ কোনটি?

  • --no-deps দিয়ে জোর করে ইনস্টল করা
  • numpy<2 শর্তটি কেন দেওয়া হয়েছিল খুঁজে সেই কোড হালনাগাদ করা, তারপর শর্ত বাদ
  • uv.lock খুলে numpy-র version হাতে বদলে দেওয়া
  • Python 3.15-এ চলে যাওয়া

ব্রাউজারে Pyodide দিয়ে চলা একটি শেখার পাতায় নিচের কোনটি করা যায় না?

  • NumPy দিয়ে একটি ছোট array-র যোগফল বের করা
  • sys.platform পড়ে দেখা কোথায় চলছে
  • subprocess দিয়ে uv add torch চালিয়ে GPU-তে model শেখানো
  • try/except দিয়ে ModuleNotFoundError ধরে বার্তা দেখানো

শব্দকোষ

লেখার মধ্যে ডটেড দাগ দেওয়া শব্দে মাউস রাখুন বা চাপুন — অর্থ দেখাবে। এই পর্বের সব নতুন শব্দ এখানে একসাথে:

মনে রাখুন

  1. Python AI-এর ভাষা হয়েছে তার library-স্তরের জন্য; ভারী হিসাব চলে C/Fortran-এ, আর সবার ভিত্তি NumPy.
  2. Python version বাছুন library দেখে: এই কোর্সে 3.14; নতুন Python-এ compile করা library-র wheel আসতে দেরি হতে পারে।
  3. uv-এ init → add → run, আর হুবহু রেকর্ড uv.lock-এ; অন্য কম্পিউটারে uv sync --locked.
  4. venv + pip একই কাজ করে; requirements.txt তালিকা, lockfile পূর্ণ রসিদ। সবসময় python -m pip.
  5. ModuleNotFoundError প্রায়ই ভুল পরিবেশ; conflict-এর error কারণ-শিকল লিখে দেয় — পড়ে একটি শর্ত বদলান, চাপা দেবেন না।

পরের পর্বে: পরিবেশ তৈরি। এবার ডেটা নিয়ে খেলার সবচেয়ে জনপ্রিয় জায়গা — Jupyter notebook: cell, kernel, magic কমান্ড, আর notebook-এর লুকানো অবস্থার ফাঁদ এড়ানোর ভালো অভ্যাস।

আরও পড়ুন · ABCL TECH-এ আপনার পরবর্তী পদক্ষেপ

এই পর্বটি শেয়ার করুন:
এই পর্বে ভুল পেয়েছেন? জানান