৫ টি পাইথন কথন

Standard

পাইথন কথন ১ঃ

#! /usr/bin/env python

এটা কি?

অনেক পাইথন স্ক্রিপ্ট এর শুরুতেই এরকম একটা লাইন দেখতে পাওয়া যায়। আসলে এর মাধ্যমে নির্দিষ্ট করে এই স্ক্রিপ্টটির ডিফল্ট ইন্টারপ্রেটার কোনটা হবে সেটা ডিফাইন করে দেয়া হয়।
অর্থাৎ টার্মিনালে chmod +x file.py কমান্ড দিয়ে file.py কে এক্সিউকিউটেবল বানিয়ে অতঃপর ./file.py কমান্ড দিয়ে সেটাকে এক্সিকিউট করতে চাইলে তার জন্য কোন ইন্টারপ্রেটার ব্যবহার হবে সেটা নির্ধারণ করে দেয়া হয়। এখানে Unix টাইপ সিস্টেমের ডিফল্ট পাইথনকে উক্ত স্ক্রিপ্ট বা ফাইলের ইন্টারপ্রেটার হিসেবে উল্লেখ্য করে দেয়া হচ্ছে। কিন্তু কিভাবে?
env হচ্ছে Unix সিস্টেমের মধ্যে থাকা একটা এক্সিকিউটেবল বাইনারি যে কিনা উক্ত সিস্টেমের সব এনভ্যায়রনমেন্ট ভ্যারিয়েবল গুলোকে খুঁজে নিতে পারে। তাই এর মাধ্যমে বস্তুত Python এর এক্সিকিউটেবল python -কে এই স্ক্রিপ্ট এর জন্য ব্যবহার করতে বলা হচ্ছে।
যেহেতু এই লাইনটির উদ্দেশ্য হচ্ছে Python কে চিনিয়ে দেয়া। তাই নিচের মত করেও এটা ডিফাইন করা যায়।

#! /usr/bin/python</code>

ধরে নিচ্ছি এটাই ওই সিস্টেমের python এর পাথ। কিন্তু এটা অ্যাবস্যুলেট পাথ। এক এক সিস্টেমে এক এক পাথে python থাকতে পারে। আমি আমার সিস্টেমে which python কমান্ড ইস্যু করে এটা পেয়েছি তাই এটা লিখলাম। এই অ্যাবস্যুলেট পাথের ঝামেলা মেটাতেই /usr/bin/env ব্যবহার করে python কে খুঁজে (যেখানেই থাকুক) সেটাকে ব্যবহার করতে বলা হয়।
এতক্ষণে বুঝে ফেলার কথা কিভাবে আমার এক্সিকিউটেবল পাইথন স্ক্রিপ্ট গুলোকে আমি Python 3 দিয়ে সবসময় রান করাতে পারবো। আমি স্ক্রিপ্টের শুরুতে নিচের মত করে Shebang লিখবো,

#! /usr/bin/env python3

পাইথন কথন ২ঃ
অনেকেই অফিসিয়াল ডকুমেন্টেশন থেকে বিভিন্ন ফাংশনের Signature পড়ার সময় বুঝে উঠতে পারে না আসলে এর প্যারামিটার গুলো কি। যেমন – round(number[, ndigits])
https://docs.python.org/3/library/functions.html#round

এটাকে বলে ফাংশন সিগনেচার। এর মাধ্যমে বুঝে নিতে হয় এই ফাংশনের প্যারামিটার গুলো কি এবং কেমন। যেমন এই ফাংশনের প্রথম প্যারামিটার ‘number’ অবশ্যই দিতে হবে অর্থাৎ Compulsory. আবার [, ] দিয়ে বোঝানো হয় এই প্যারামিটার গুলো Optional. আর তাই, [ ] এর বাইরে যেগুলো থাকবে সেগুলো অবশ্যই দিতে হবে আর ভিতরে যেগুলো থাকবে সেগুলো না দিলেও ওই ফাংশন কাজ করবে। কিন্তু,
[ ] এর মধ্যে থাকা অপশনাল প্যারামিটার গুলোর মধ্যে কিছু ডিপেন্ডেন্সিও থাকতে পারে। যেমন – RegexObject.match(string[, pos[, endpos]])
এখানে বোঝানো হয়েছে ‘endpos’ পাস করলে অবশ্যই ‘pos’ -ও পাস করতে হবে। তাই এগুলো একটা নেস্টেড ব্র্যাকেটের মধ্যে নির্দেশ করা হয়েছে। আবার শুধু ‘pos’ দিয়ে ‘endpos’ না দিলেও চলবে।

পাইথন কথন ৩ঃ
Python প্রোগ্রাম বলতে আমরা যা ব্যবহার করি তা হচ্ছে CPython. এই, CPython হচ্ছে আসলে Python এর একটা ডিফল্ট এবং বহুল ব্যবহৃত ইমপ্লিমেন্টেশন। এই ইমপ্লিমেন্টেশন জিনিষটা কি?
Python বা অন্য প্রোগ্রামিং ল্যাঙ্গুয়েজ গুলো হচ্ছে ফর্মাল ল্যাঙ্গুয়েজ অর্থাৎ একটু এদিক সেদিক করে এসব ভাষা ব্যবহার করলে কাজ হবে না। এটা বাংলা বা ইংলিশ এর মত ইনফর্মাল না যে – মুরাদ টাকলাদের ভাষাতেও কিছু লিখলে বুঝে নেয়া যায়।
যাই হোক সিমপ্লি, ল্যাঙ্গুয়েজ রেফারেন্স হিসেবে চিন্তা করলে Python -কে একটা ইন্টারফেসও বলা যেতে পারে। যারা প্রোগ্রামিং করেন তারা এই টার্ম সম্পর্কে জানেন – ইন্টারফেস হচ্ছে এক ধরণের অ্যাবসট্র্যাকশন যার মাধ্যমে নির্ধারণ করে দেয়া হয় একটা নির্দিষ্ট কাজ কিভাবে হবে কিন্তু ইমপ্লিমেন্টেশনটা যার যেমন ইচ্ছা সেভাবে করবে। তাই, CPython বস্তুত Python এর Language Reference মেনে C দিয়ে করা একটা ইমপ্লিমেন্টেশন। আবার, CPython -ই হচ্ছে Python প্রোগ্রামের ইন্টারপ্রেটার 😛

একটা পাইথন প্রোগ্রামের এক্সিকিউশনের ধাপ গুলো এরকমঃ

Python Source Code (.py) -> Compiler -> Bytecode (.pyc) -> Interpreter (VM/CPython) -> Output (Hello World!)

যখন নির্দিষ্ট কোন কাজের সাপেক্ষে বলা হয় Python স্লো বা ফাস্ট তখন আসলে দোষ বা বাহবা যেটাই দেয়া হোক, দিতে হবে CPython কে অথবা ওই নির্দিষ্ট ইমপ্লিমেন্টেশনকে 🙂
Python এর এরকম আরও অনেক ইমপ্লিমেন্টেশন আছে। যেমন- Jython, IronPython, PyPy ইত্যাদি। Jython এর ক্ষেত্রেও বিষয়টা একই। অর্থাৎ – Python নামক ফর্মাল ল্যাঙ্গুয়েজের ইমপ্লিমেন্টেশন করা হয়েছে Java তে। তাই Python এর এই ভার্সনেও স্বাভাবিক Python এর সিনট্যাক্স মোতাবেকই প্রোগ্রাম লেখা যাবে এবং প্রোগ্রাম রান করালে এর পিছনে আসলে কলকাঠি নাড়বে Java.
অন্যান্য প্রোগ্রামিং ল্যাঙ্গুয়েজের ক্ষেত্রেও বিষয়টা এরকম। যেমন, যদি বলা হয়ঃ C++ is implemented in C. এর মানে সহজ ভাবে বলতে গেলেঃ C++ এর কম্পাইলার C দিয়ে তৈরি 🙂
আরেকটা কথা, উপরের এক্সিকিউশনের ধাপ অনুযায়ী Python কে ইন্টারপ্রেটেড বা কম্পাইল্ড ল্যাঙ্গুয়েজ কোনটাই বলা যাবে না (সিরিয়াসলি?)। আসলে Python কিন্তু ইন্টারপ্রেটেড বা কম্পাইল্ড না। যদি এই বৈশিষ্ট্য কাউকে দিতেই হয় তাহলে CPython কে দিতে হবে।
CPython ইন্টারপ্রেটেড কিন্তু (আবার কি?) তার আগে একটা কম্পাইলেশন স্টেপ আছে 😛 যেটা [প্রোগ্রাম টু প্রসেসর] কনসেপ্ট অনুযায়ী এখানে অগ্রাহ্য)

পাইথন কথন ৪ঃ

# -*- coding: utf-8 -*-

এই কমেন্ট লাইনটাকে অনেক পাইথন স্ক্রিপ্টের শুরুতেই দেখা যায়। একটু একটু বোঝা যায় যে এখানে এনকোডিং ডিফাইন করে দেয়া হয়েছে। কিন্তু কিসের এবং কেন? কার জন্যই বা দরকার এটা?
প্রথমেই জানতে হবে কম্পিউটারের সাথে টেক্সট নিয়ে কাজ করতে হলে তাকে টেক্সট গুলো চেনাতে হয়, আর আমরা সবাই জানি কম্পিউটার 1, 0 ছাড়া আর কাউকেই চেনে না। তো এনকোডিং এর সহজ মানে হচ্ছে একটা ম্যাপিং টেবিল যেখানে বলা আছে A এর মানে 01000001 (এটা ASCII এনকোডিং/টেবিল)। কিন্তু এই টেবিলে দুনিয়ার সব ভাষার সব ক্যারেক্টার এর সাপেক্ষে এরকম কম্পিউটার উপযোগী কোড নাই। এদিকে আমাদের প্রোগ্রাম লিখতে বা টেক্সট ফাইল লিখতে সেই ক্যারেক্টার গুলো লাগতেই পারে। তাই এরকম আরও একটা বিশাল লম্বা টেবিল আছে, utf-8 এনকোডিং/টেবিল। এই টেবিলে বাংলা “ক” সাপেক্ষেও একটা বাইনারি পাওয়ার ব্যবস্থা আছে।
তো আমাদের পাইথন প্রোগ্রামে যদি এরকম ASCII এর বাইরের ক্যারেক্টার থাকে তাকে চেনাতে হলে ফাইলের শুরুতে বলে দিতে হবে যে – ভাই পাইথন তুমি আমার এই সোর্স ফাইলকে দয়া করে utf-8 টেবিল/এনকোডিং মোতাবেক পার্স করিয়ো নাহলে বুঝবা না আমি ফাইলে কি লিখছি 🙂
নিচের প্রোগ্রামটা যদি একটা Test.py ফাইলে লিখে পাইথন ২ দিয়ে রান করাই,

name = "নুহিল"
print(name)

তাহলে আউটপুট আসবে,

File "Test.py", line 3
SyntaxError: Non-ASCII character '\xe0' in file Test.py on line 3

তাই ওই Test.py কে আপডেট করে নিচের মত করতে হবে,

# -*- coding: utf-8 -*-
name = "নুহিল"
print(name)

এবার ঠিকঠাক রান করবে। আর হ্যা, ঠিক # -*- coding: utf-8 -*- এভাবেই যে সোর্স ফাইলের এনকোডিং ডিফাইন করতে হবে তাও কিন্তু না। # Please encoding: utf-8 (সত্যি) এরকম লিখলেও পাইথন বুঝে যাবে 🙂
শেষ কথা, এই ঝক্কি ঝামেলা কিন্তু Python 3 তে করতে হবে না কারন পাইথন ৩ ডিফল্ট এনকোডিং হিসেবে utf-8 কেই ধরে নেয় 😀

পাইথন কথন ৫ঃ

if __name__ == "__main__":

এই লাইনটা অনেক পাইথন ফাইলে দেখে ঘাবড়ে যাবার কিছু নাই। আমরা বোঝার চেষ্টা করি কেন লোকজন এই অদ্ভুত if কন্ডিশনটাকে তাদের পাইথন স্ক্রিপ্টে লিখে।
পাইথন ইন্টারপ্রেটার একটি প্রোগ্রামের এক্সিকিউশনের আগে যখন একটি সোর্স ফাইলকে পার্স (পড়ে) করে তখন সে এর জন্য কিছু স্পেশাল ভ্যারিয়েবল সেট করে। যখন স্বাধীনভাবে কোন পাইথন স্ক্রিপ্টকে রান করানো হয় তখন স্বয়ংক্রিয়ভাবে এর জন্য একটি __name__ নামের ভ্যারিয়েবল তৈরি হয় যার ভ্যালু সেট করা হয় স্ট্রিং “__main__” .
তাই আমরা যদি চাই আমাদের স্ক্রিপ্ট এর মধ্যেকার কিছু স্টেটমেন্ট শুধুমাত্র তখনি কাজ করুক যখন এটা একটা স্ট্যান্ডঅ্যালোণ স্ক্রিপ্ট হিসেবে রান করবে তখন বুদ্ধি করে এরকম একটা if কন্ডিশন লিখে তার মধ্যে ওগুলো লিখবো। কারন আমরা তো জানিই যে এই if কন্ডিশন তখনি সত্য হবে যখন এই স্ক্রিপ্টটা শুধু স্ক্রিপ্ট হিসেবেই রান হবে।
যেমন আমাদের যদি নিচের মত একটা প্রোগ্রাম থাকে Nuhil.py ফাইলে,

def my_module_func():
    print("Nuhil Mehdy")

if __name__ == "__main__":
    print("Nuhil")

তাহলে আমরা যখন python Nuhil.py এভাবে একে রান করাবো তখন আউটপুট আসবে,
Nuhil
কিন্তু (আবার কি হল?),
যদি এই Nuhil.py কে আরেকটি পাইথন ফাইল যেমন Mehdy.py এর মধ্যে মডিউল হিসেবে import করি তখন কিন্তু পাইথন এই Nuhil.py ফাইল পার্স (পড়ার সময়) করার সময় __name__ নামের ভ্যারিয়েবলের জন্য “__main__” ভ্যালু সেট করবে না। আর তাই if কন্ডিশনটা মিথ্যা হবে। তো, Mehdy.py এর কোড যদি হয় নিচের মত,

import Nuhil
Nuhil.my_module_func()

তাহলে আউটপুট আসবে,

Nuhil Mehdy

এবং সুন্দর মত print("Nuhil") স্টেটমেন্টটি গু(?)পনেই থেকে যাবে

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s