মাছের তেলে মাছ পর্ব ১

পাইথন আমার সবচেয়ে পছন্দের প্রোগ্রামিং ল্যাঙ্গুয়েজ এর একটি। এটি আবার আমার জীবিকার মাধ্যমো। তাই ভাবলাম আমার এই তৃতীয় ব্লগ পোস্ট পাইথনের উপর লিখি এবং তাও একটু ভিন্নভাবে। এই পোস্টটি লিখা হবে IPython দিয়ে এবং এর মূল বিষয়ও হবে IPython ভিত্তিক (কাজেই এই শিরোনাম)। তাহলে শুরু করা যাক।

IPython কী? এক কথায় বলতে গেলে এটি একটি পরিবেশ যেখানে আপনি পাইথন (এবং অন্যান্য কিছু ল্যাঙ্গুয়েজ) প্রোগ্রামিং করতে পারেন। প্রথম দেখায় মনে হবে যে এটি অত্যন্ত শক্তিশালী একটি শেল। আমার প্রথম পরিচয় IPython এর সাথে ছিল অনেক আগে, তখনকার সংজ্ঞানুযায়ী হয়ত "শক্তিশালী শেল" ঠিক ছিল। কিন্তু কয়েকবছর ধরে যে আপডেট আসছে IPython এ, তাতে মনে হবে যে এটি "শেল" উপাধি ছাড়িয়ে হয়ে উঠেছে অন্যকিছু। এই পোস্টে আমি সেটি তুলে ধরব।

প্রথমেই ইন্সটল করা যাক। pip install ipython চলবে আপাতত। তাহলে করা যাক। আপনি terminal এ যেয়ে ipython টাইপ করলেই আপনি চলে আসবেন ipython শেলে। প্রথম দেখাতে মনে হবে যে এটি একটু উন্নতমানের শেল যেখানে ট্যাব বোতাম প্রেস করলেই অটোকমপ্লিট করে দেয়, কিন্তু ipython আরও অনেক কিছু, সেটি আপনি বুঝতে পারবেন যখন আপনি কোন পাইথন সঙ্কেত paste করবেন। আপনি আপনার সিস্টেমের paste শর্টকাট ব্যবহার না করে ipython এর magic command ব্যবহার করবেন যা হল %paste, কোন পাইথন সঙ্কেত কপি করে ipython এ গিয়ে %paste লিখে দেখুনতো? আরও মজার বিষয়, যে কোন ফাংশন লিখে ? অথবা ?? দিয়েই বা দেখুন? যেমন (যদি আপনি import os করে থাকেন) os? অথবা os.system? অথবা os.path??... "?" আপনাকে নিয়ে যাবে ডকুমেন্টেশনে আর ?? এর মাধ্যমে আপনি ওই ফাংশন অথবা মডুলের সোর্স দেখতে পাবেন। আর যদি আপনি a*? দিন, তাহলে a দিয়ে শুরু হয় এমন সকল অবজেক্ট এর লিস্ট দিবে আপনাকে। os.system থেকে মনে পরল, আপনি যদি ipython শেলে থাকাকালীন সময়ে চান bash কমান্ড টাইপ করতে তাহলে আপনার ipython শেলে ! যোগ করুন আপনার কমান্ডের পূর্বে। উদাহরণস্বরূপঃ

In [9]:
!ls
Applications                   Public
Apps                           PycharmProjects
Books                          RubymineProjects
Codes                          _vimrc
Desktop                        adt-bundle-mac-x86_64-20130917
Documents                      nltk_data
Downloads                      node_modules
IPython Blog Part 1.ipynb      requirements.txt
Library                        tbl_raw.csv
Movies                         test.py
Music                          tmp
Pictures

আপনি কি জানতে চান আপনার কোড চলতে কেমন সময়ে নেয়? আপনার জন্য রয়েছে %timeit ম্যাজিকঃ

In [14]:
import random as rd
%timeit sorted([rd.random() for i in range(10000000)])
1 loops, best of 3: 17.2 s per loop

এরকম আরও অনেক ম্যাজিক কম্যান্ড রয়েছে ipython এ, যা মূলত আপনার ইন্টার‌্যাক্টিভ পাইথন প্রোগ্রামিংকে করে তোলে সহজ ও মজাদার। আমার একটি পছন্দের ম্যাজিক হলও "/"। / এর পর আপনি যেই ফাংশন দিবেন সেটাতে কোন ব্রাকেটের প্রয়োজন পরে না (রুবি স্টাইল)।

In [26]:
/ord "A"
Out[26]:
65

আপনি নিশ্চয় জানেন যে এর মাধ্যমে আপনি ঠিক আগের রেজাল্ট পাচ্ছেন শেলে। ipython আপনাকে আরেকটু সুবিধা দিয়ে থাকে। আপনি দেখছেন যে In [] এবং Out [] প্রতি লাইনে রয়েছে? বোঝা সহজ যে In দ্বারা Input ও Out দ্বারা Output বোঝানো হয়েছে এবং ব্রাকেটের মাঝখানের নাম্বার হলও লাইন নাম্বার। কিন্তু যদি আপনি লাইন নাম্বারের পাইথন মান চান তাহলে? দিয়ে তো শুধু ঠিক আগের মান পাওয়া যায়, কিন্তু _i ও _ দিয়ে আপনি line_numer এর ইনপুট ওর অউটপুট পাবেন। %history ম্যাজিক হল IPython এর "history" কমান্ড। একটু দেখুনঃ

In [32]:
1+1
Out[32]:
2
In [33]:
2+2
Out[33]:
4
In [34]:
_i32
Out[34]:
u'1+1'
In [35]:
_33
Out[35]:
4
In [36]:
%history
%paste
%paste
%help
qs = lambda xs : ( (len(xs) <= 1 and [xs]) or
                     [ qs( [x for x in xs[1:] if x < xs[0]] ) +
                           [xs[0]]                            +
                       qs( [x for x in xs[1:] if x >= xs[0]] ) ] )[0]
qs?
qs??
!ls
%cpaste
!ls
%
%timeit
%timeit [i for i in range(10000)]
import random

%timeit (lambda xs : ( (len(xs) <= 1 and [xs]) or
                     [ qs( [x for x in xs[1:] if x < xs[0]] ) +
                           [xs[0]]                            +
                       qs( [x for x in xs[1:] if x >= xs[0]] ) ] )[0])([random.random() for i in range(1000000)])
import random as rd
%timeit sorted([rd.random() for i in range(10000000)])
%pprint
%pprint
%pprint [1,2,3]
%pprint
paste
%%paste
%magic
%dhist
/str 12
/str 420
/sorted [random.random() for i in range(10)]
/ord "A"
i_14
%i_14
_i14
table = [[1,2,3],[4,5,6],[7,8,9]]
table
1+1
2+2
_i32
_33
%history

হাহা! এই পোস্ত লিখার সময়ে আমি অনেক এক্সপেরিমেন্ট করেছি, তাই ওইসব অতিরিক্ত লাইন।

আমার এমন প্রায়েই হয় যে শেলে এক্সপেরিমেন্ট করতে করতে অনেক ফাংশন লিখে ফেলি যা আবার উপরে গিয়ে কপি করা লাগে। এমন যদি হয়ে থাকে, তাহলে আপনি %%writefile সাহায্য নিনঃ

In [37]:
%%writefile ipython_html.py
class ListTable(list):
    """ Overridden list class which takes a 2-dimensional list of 
        the form [[1,2,3],[4,5,6]], and renders an HTML Table in 
        IPython Notebook. """
    
    def _repr_html_(self):
        html = ["<table>"]
        for row in self:
            html.append("<tr>")
            
            for col in row:
                html.append("<td>{0}</td>".format(col))
            
            html.append("</tr>")
        html.append("</table>")
        return ''.join(html)
import random
table = ListTable()
table.append(['x', 'y', 'x-y', '(x-y)^2'])
for i in xrange(7):
    x = random.uniform(0, 10)
    y = random.uniform(0, 10)
    table.append([x, y, x-y, (x-y)**2])
table
Writing ipython_html.py
In [38]:
!ls ipython_html.py
ipython_html.py
In [39]:
!cat ipython_html.py
class ListTable(list):
    """ Overridden list class which takes a 2-dimensional list of 
        the form [[1,2,3],[4,5,6]], and renders an HTML Table in 
        IPython Notebook. """
    
    def _repr_html_(self):
        html = ["<table>"]
        for row in self:
            html.append("<tr>")
            
            for col in row:
                html.append("<td>{0}</td>".format(col))
            
            html.append("</tr>")
        html.append("</table>")
        return ''.join(html)
import random
table = ListTable()
table.append(['x', 'y', 'x-y', '(x-y)^2'])
for i in xrange(7):
    x = random.uniform(0, 10)
    y = random.uniform(0, 10)
    table.append([x, y, x-y, (x-y)**2])
table

জটিল না? আর ওই কোডটি নেওয়া হয়েছে http://calebmadrigal.com/display-list-as-table-in-ipython-notebook/ থেকে।

আপনি যদি অন্যান্য ম্যাজিক কমান্ড সম্পর্কে জানতে ইচ্ছুক থাকেন তাহলে %magic টাইপ করুন ipython শেলে। আর আপনি যদি pdb ব্যবহার করে থাকেন তাহলে হয়ত আপনি %debug, %profile, %pdb ইত্যাদি কম্যান্ডের প্রতি নজর রাখতে পারেন। আর আপনি ? এর মাধ্যমে মাজিক কম্যান্ডের ব্যবহারবিধি জেনে নিতে পারেনঃ

In [43]:
%pwd?

যদি রুবি প্রোগ্রামিং করতে ইচ্ছে করে তাহলেঃ

In [45]:
%%ruby
puts "Ruby is also an awesome language"
Ruby is also an awesome language

%run কমান্ড দিয়ে আপনি যে কোন পাইথন ফাইল চালাতে পারবেন। notebook পর্বের পূর্বে আপনাকে দেখিয়ে দিচ্ছি ম্যাজিক কমান্ডের লিস্ট

In [47]:
%lsmagic
Out[47]:
Available line magics:
%alias  %alias_magic  %autocall  %automagic  %autosave  %bookmark  %cd  %clear  %colors  %config  %connect_info  %debug  %dhist  %dirs  %doctest_mode  %ed  %edit  %env  %gui  %hist  %history  %install_default_config  %install_ext  %install_profiles  %killbgscripts  %less  %load  %load_ext  %loadpy  %logoff  %logon  %logstart  %logstate  %logstop  %lsmagic  %macro  %magic  %man  %matplotlib  %more  %notebook  %page  %pastebin  %pdb  %pdef  %pdoc  %pfile  %pinfo  %pinfo2  %popd  %pprint  %precision  %profile  %prun  %psearch  %psource  %pushd  %pwd  %pycat  %pylab  %qtconsole  %quickref  %recall  %rehashx  %reload_ext  %rep  %rerun  %reset  %reset_selective  %run  %save  %sc  %store  %sx  %system  %tb  %time  %timeit  %unalias  %unload_ext  %who  %who_ls  %whos  %xdel  %xmode

Available cell magics:
%%!  %%HTML  %%SVG  %%bash  %%capture  %%debug  %%file  %%html  %%javascript  %%latex  %%perl  %%prun  %%pypy  %%python  %%python3  %%ruby  %%script  %%sh  %%svg  %%sx  %%system  %%time  %%timeit  %%writefile

Automagic is ON, % prefix IS NOT needed for line magics.

এবার যাওয়া হোক notebook পর্বে। যদিও আমি দ্বিতীয় পর্বে আরও বিস্তারিত আলোচনা করব, তবে ছোট একটি টিজার হয়ে যাক? ঠিক আছে, আপনি আপনার প্রিয় (আমি আশা করি পাওয়ার শেল না) শেলে গিয়ে টাইপ করুনঃ ipython notebook এবং আপনার প্রিয় (আমি আশা করি ক্রম) ব্রাউজারে যেয়ে localhost:8888 (অথবা যেই পোর্ট আপনার নোটবুক সাপোর্ট করে) টাইপ করুন এবং দেখুন আপনাকে কোথায় নিয়ে যায় ipython.

ipython notebook এ আপনি আপনার ব্রাউজারে দেখতে পাবেন আপনার ইনপুট/অউটপুট, সাথে যদি ইমেজ অথবা গ্রাফ থাকে, তাও দেখতে পাবেন। আপনাকে একটি ঝটিকা সফর করাই আসুনঃ

In [54]:
from IPython.display import YouTubeVideo, ScribdDocument, Image
YouTubeVideo("99dmQGPkvog")
Out[54]:
In [49]:
Image("http://imgs.xkcd.com/comics/python.png")
Out[49]:
In [51]:
 ScribdDocument(57352264, width=800, height=400, start_page=3, view_mode="book")
Out[51]:
In [66]:
class ListTable(list):
    """ Overridden list class which takes a 2-dimensional list of 
        the form [[1,2,3],[4,5,6]], and renders an HTML Table in 
        IPython Notebook. """
    
    def _repr_html_(self):
        html = ["<table>"]
        for row in self:
            html.append("<tr>")
            
            for col in row:
                html.append("<td>{0}</td>".format(col))
            
            html.append("</tr>")
        html.append("</table>")
        return ''.join(html)

    
import random


table = ListTable()
table.append(['x', 'y', 'x-y', '(x-y)^2'])
for i in xrange(7):
    x = random.uniform(0, 10)
    y = random.uniform(0, 10)
    table.append([x, y, x-y, (x-y)**2])
table
Out[66]:
xyx-y(x-y)^2
7.360474224822.39818924834.9622849765224.6242721882
5.804031751471.268404799744.5356269517320.5719118453
4.333103614568.63676500911-4.3036613945518.5215013989
1.328536512882.44226297309-1.113726460211.24038662818
8.209249429451.03056203917.1786873903551.5335526484
7.470189218830.0408988248347.4292903939955.1943557583
2.670687381432.43748860840.2331987730330.054381667744
In [64]:
HTML """<iframe width="100%" 
  height="166" 
  scrolling="no" 
  frameborder="no" 
  src="https://w.soundcloud.com/player/?url=https%3A//api.soundcloud.com/tracks/85157364&amp;color=ff6600&amp;auto_play=false&amp;show_artwork=true">
  </iframe>""")
  File "<ipython-input-64-dbb6e2022a0e>", line 6
    </iframe>""")
                 
^
SyntaxError: invalid syntax
In [55]:
#Oops!!!
In [65]:
from IPython.display import HTML


HTML("""<iframe width="100%" 
  height="166" 
  scrolling="no" 
  frameborder="no" 
  src="https://w.soundcloud.com/player/?url=https%3A//api.soundcloud.com/tracks/85157364&amp;color=ff6600&amp;auto_play=false&amp;show_artwork=true">
  </iframe>""")
Out[65]:

আচ্ছা আমার এই মেশিনে কি matplotlib আছে?

In [6]:
%matplotlib inline
import numpy as np

from pylab import *
from matplotlib import pyplot as plt
In [2]:
n = np.random.randn(100000)
fig, axes = plt.subplots(1, 2, figsize=(12,4))

axes[0].hist(n)
axes[0].set_title("Default histogram")
axes[0].set_xlim((min(n), max(n)))

axes[1].hist(n, cumulative=True, bins=50)
axes[1].set_title("Cumulative detailed histogram")
axes[1].set_xlim((min(n), max(n)));
In [1]:
%matplotlib inline
from matplotlib import pyplot as plt
import numpy as np

plt.plot(np.random.rand(100))
fig = plt.gcf()
In [10]:
from pylab import *
from matplotlib.patches import Polygon

def func(x):
    return (x-3)*(x-5)*(x-7)+85

ax = subplot(111)

a, b = 2, 9 # integral area
x = arange(0, 10, 0.01)
y = func(x)
plot(x, y, linewidth=1)

# make the shaded region
ix = arange(a, b, 0.01)
iy = func(ix)
verts = [(a,0)] + list(zip(ix,iy)) + [(b,0)]
poly = Polygon(verts, facecolor='0.8', edgecolor='k')
ax.add_patch(poly)

text(0.5 * (a + b), 30,
     r"$\int_a^b f(x)\mathrm{d}x$", horizontalalignment='center',
     fontsize=20)

axis([0,10, 0, 180])
figtext(0.9, 0.05, 'x')
figtext(0.1, 0.9, 'y')
ax.set_xticks((a,b))
ax.set_xticklabels(('a','b'))
ax.set_yticks([])
show()

বিস্তারিতঃ এইখানে এবং এইখানে

আজকে আপাতত এতটুকু থাকুক। ও ভুলেই গিয়েছিলাম, আপনি ipython notebook কে পাবলিশ কিভাবে করবেন? সহজ, আপনার নোটবুক ফাইল সেভ করুন, Gist এ কপি করুন আপনার ফাইলের কনটেন্ট এবং ওই gist নাম্বার দিয়ে দিন http://nbviewer.ipython.org/ সাইটটিতে।

আবার দেখা হবে আমার ব্লগে অথবা পাইচারমারে অথবা পলিগ্লট প্রোগ্রামার এ। ভাল থাকুন।

In [ ]: