Advanced Python Training at VMWare - Day 3

Nov 20-22, 2017 Vikrant Patil

These notes will be available online at http://notes.pipal.in/2017/vmware-nov-advpython/ after this training!

© Pipal Academy LLP

Day 1 | Day 2 | Day 3

Classes

In [1]:
def f(x):
    print(x)
    return 2*x
In [2]:
f(2)
2
Out[2]:
4
In [3]:
x
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
<ipython-input-3-401b30e3b8b5> in <module>()
----> 1 x

NameError: name 'x' is not defined
In [4]:
amount = 10000
balance = 50000

def withdraw(balance, amount):
    balance = balance - amount
    return balance

fixdep = withdraw(balance, amount)
print("balance ", balance)
print("amount ",amount) 
balance  50000
amount  10000

changing scope of a variable

In [6]:
hello = "Hello initial"

def firstlevel():
    hello = "Hello inside first level"
    
    def secondlevel1():
        hello = "Hello inside secondlevel1"
        
    def secondlevel2():
        nonlocal hello
        hello = "hello from secondlevel2"
        
        def thirdlevel():
            global hello
            hello = "from thirdlevel"
        
        thirdlevel()
        print(hello)
        
    secondlevel1()
    secondlevel2()
        
firstlevel()
print("*"*5, hello)
hello from secondlevel2
***** from thirdlevel

What will be output of this?

def f(x):
    x.append(5)

def g(x):
    x = [1,1,1,1,1]

l = [1,2,3,4]
f(l)
print(l)
g(l)
print(l)
In [7]:
def f(x):
    x.append(5)

def g(x):
    x = [1,1,1,1,1]

l = [1,2,3,4]
In [8]:
f(l)
In [9]:
l
Out[9]:
[1, 2, 3, 4, 5]
In [10]:
g(l)
In [11]:
l
Out[11]:
[1, 2, 3, 4, 5]

Classes

systactically class looks like this

class ClassName:
      <statement>
      <statement>
      .
      .
      .
In [12]:
import math

class Circle:
    
    def __init__(self, radius):
        self.radius = radius
        
    def area(self):
        return math.pi * self.radius**2
    
class Square:
    def __init__(self, side):
        self.side = side
        
    def area(self):
        return self.side**2
    
class Triangle:
    def __init__(self, base, height):
        self.base = base
        self.height = height
        
In [13]:
c = Circle(1.0)
In [14]:
s = Square(1.0)
In [15]:
t = Triangle(1, 1)
In [16]:
c.area()
Out[16]:
3.141592653589793
In [17]:
shapes = [Circle(1.0), Circle(2.0), Square(1.0), Square(2.0)]
In [18]:
areas = [s.area()  for s in shapes]
In [19]:
shapes.append(Triangle(1, 1))
In [20]:
shapes
Out[20]:
[<__main__.Circle at 0x7f7e600cca20>,
 <__main__.Circle at 0x7f7e600cc240>,
 <__main__.Square at 0x7f7e600cc358>,
 <__main__.Square at 0x7f7e600cc470>,
 <__main__.Triangle at 0x7f7e600cc208>]
In [21]:
print(areas)
[3.141592653589793, 12.566370614359172, 1.0, 4.0]
In [22]:
areas = [s.area()  for s in shapes]
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-22-8f78782de04f> in <module>()
----> 1 areas = [s.area()  for s in shapes]

<ipython-input-22-8f78782de04f> in <listcomp>(.0)
----> 1 areas = [s.area()  for s in shapes]

AttributeError: 'Triangle' object has no attribute 'area'
In [23]:
%%file bank0.py

balance = 0

def deposite(amount):
    global balance
    balance = balance + amount
    
def withdraw(amount):
    global balance
    balance = balance - amount

def get_balance():
    return balance

def main():
    print(get_balance())
    deposite(100)
    print(get_balance())
    withdraw(20)
    print(get_balance())


if __name__ == "__main__":
    main()
Writing bank0.py
In [24]:
!python bank0.py
0
100
80
In [32]:
%%file bank1.py

def make_account():
    return {"balance":0}

def deposite(account, amount):
    account['balance'] += amount
    
def withdraw(account, amount):
    account['balance'] -= amount
    
def get_balance(account):
    return account['balance']

def main():
    a1 = make_account()
    a2 = make_account()
    print("a1:",get_balance(a1))
    deposite(a1, 100)
    print("a1:",get_balance(a1))
    deposite(a2, 200)
    withdraw(a2, 20)
    print("a2:",get_balance(a2))


if __name__ == "__main__":
    main()
Overwriting bank1.py
In [33]:
!python bank1.py
a1: 0
a1: 100
a2: 180
In [34]:
%%file bank2.py
"""
class based implementation of bank account
"""

class BankAccount:
    
    def __init__(self):
        self._balance = 0
        
    def deposite(self, amount):
        self._balance += amount
        
    def withdraw(self, amount):
        self._balance -= amount
        
    def get_balance(self):
        return self._balance
    
def main():
    a1 = BankAccount()
    a2 = BankAccount()
    a1.deposite(100)
    a2.deposite(200)
    print("a1: {balance1}, a2: {balance2}".format(balance1=a1.get_balance(),
                                                 balance2=a2.get_balance()))
    a1.withdraw(20)
    a2.withdraw(30)
    print("a1: {balance1}, a2: {balance2}".format(balance1=a1.get_balance(),
                                                 balance2=a2.get_balance()))
    
if __name__ == "__main__":
    main()
Writing bank2.py
In [35]:
!python bank2.py
a1: 100, a2: 200
a1: 80, a2: 170

Example : text formating

In [36]:
class Formatter:
    def format_text(self, text):
        """
        Formats given text
        This implementation returns same text.
        subclasses should override this method 
        to change formatig
        """
        return text
    
    def format_file(self, name):
        text = open(name).read()
        return self.format_text(text)
In [37]:
class UpperCaseFormnatter(Formatter):
    def format_text(self, text):
        return text.upper()
In [38]:
f = UpperCaseFormnatter()
In [39]:
f.format_text("hello")
Out[39]:
'HELLO'
In [40]:
%%file five.txt
one
two
three
four
five
Writing five.txt
In [42]:
print(f.format_file("five.txt"))
ONE
TWO
THREE
FOUR
FIVE
In [43]:
class LineFormatter(Formatter):
    def format_line(self, line):
        return line
    
    def format_text(self, text):
        lines = text.split("\n")
        lines = [self.format_line(l) for l in lines]
        return "\n".join(lines)
In [44]:
class PrefixFormatter(LineFormatter):
    def __init__(self, prefix):
        self.prefix  = prefix
        
    def format_line(self, line):
        return self.prefix + line
In [45]:
f = PrefixFormatter("[Info]")
In [46]:
print(f.format_text("hello\nworld"))
[Info]hello
[Info]world
In [47]:
print(f.format_file("five.txt"))
[Info]one
[Info]two
[Info]three
[Info]four
[Info]five

Class object

In [55]:
class ClassA:
    value = 42
    
    def f(self):
        return ("Hello from ClassA")
In [49]:
ClassA
Out[49]:
__main__.ClassA
In [50]:
ClassA.value
Out[50]:
42
In [51]:
ClassA.f
Out[51]:
<function __main__.ClassA.f>

Instance object

In [52]:
a = ClassA()
In [54]:
a.__class__
Out[54]:
__main__.ClassA
In [56]:
a.value
Out[56]:
42
In [ ]:
 
In [57]:
a.f
Out[57]:
<bound method ClassA.f of <__main__.ClassA object at 0x7f7e51fe5a90>>
In [58]:
a.f()
Out[58]:
'Hello from ClassA'
In [59]:
ClassA.f()
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-59-46724427a1a8> in <module>()
----> 1 ClassA.f()

TypeError: f() missing 1 required positional argument: 'self'
In [60]:
ClassA.f(a)
Out[60]:
'Hello from ClassA'
In [61]:
a.my_own_value = 43
In [62]:
a.my_own_value
Out[62]:
43
In [63]:
ClassA.my_own_value
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-63-157c1809eb7a> in <module>()
----> 1 ClassA.my_own_value

AttributeError: type object 'ClassA' has no attribute 'my_own_value'
In [64]:
ClassA.y = 3
In [65]:
a.y
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-65-cc7049c6eeec> in <module>()
----> 1 a.y

AttributeError: 'ClassA' object has no attribute 'y'
In [66]:
ClassA.y
Out[66]:
3
In [67]:
b = ClassA()
In [68]:
b.y
Out[68]:
3
In [69]:
del ClassA.y
In [70]:
b.y
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-70-afd442275b5c> in <module>()
----> 1 b.y

AttributeError: 'ClassA' object has no attribute 'y'
In [71]:
class A:
    x = 0
    def __init__(self, v):
        self.y = v
In [75]:
a = A(2)
In [77]:
A.y
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-77-579fd00f727b> in <module>()
----> 1 A.y

AttributeError: type object 'A' has no attribute 'y'
In [78]:
a.y
Out[78]:
2
In [79]:
a.x
Out[79]:
0
In [80]:
a1 = A(3)
In [81]:
a2 = A(4)
In [82]:
a1.x
Out[82]:
0
In [83]:
a2.x
Out[83]:
0
In [84]:
A.x = 42
In [85]:
a.x
Out[85]:
42
In [86]:
a1.x
Out[86]:
42
In [87]:
a2.x
Out[87]:
42
In [88]:
a1.x = 43
In [89]:
a2.x
Out[89]:
42
In [90]:
x = ClassA()
In [91]:
method = x.f
In [92]:
method()
Out[92]:
'Hello from ClassA'
In [96]:
ClassA.f2 = lambda self, y: self.value+y
In [97]:
d = ClassA()
In [98]:
d.f2(4)
Out[98]:
46
In [100]:
a2.new1 = 32
In [101]:
a2.__dict__
Out[101]:
{'new1': 32, 'y': 4}
In [102]:
a1.__dict__
Out[102]:
{'x': 43, 'y': 3}
In [103]:
a.__dict__
Out[103]:
{'y': 2}
In [104]:
a.x
Out[104]:
42

Customizing classes

In [105]:
s = "one\ntwo"
In [106]:
s
Out[106]:
'one\ntwo'
In [107]:
print(s)
one
two
In [115]:
class Pair(object):
    def __init__(self, x, y):
        self.x = x
        self.y = y
        
    def __repr__(self):
        return 'Pair({0.x!r},{0.y!r})'.format(self)
    
    def __str__(self):
        return '({0.x!s},{0.y!s})'.format(self)
In [116]:
p = Pair(2,3)
In [117]:
p
Out[117]:
Pair(2,3)
In [118]:
print(p)
(2,3)
In [119]:
repr([1,2])
Out[119]:
'[1, 2]'
In [120]:
str([1,2])
Out[120]:
'[1, 2]'

arithmatic operators

In [122]:
class Pair(object):
    def __init__(self, x, y):
        self.x = x
        self.y = y
        
    def __repr__(self):
        return 'Pair({0.x!r},{0.y!r})'.format(self)
    
    def __str__(self):
        return '({0.x!s},{0.y!s})'.format(self)
    
    def __add__(self, p):
        return Pair(self.x+p.x, self.y+p.y)
    
    def __sub__(self, p):
        if isinstance(p, int):
            return Pair(self.x-p, self.y-p)
        else:
            return Pair(self.x -p.x, self.y-p.y)
        
    def __rmul__(self, c):
        return Pair(self.x*c, self.y*c)
    
    def __mul__(self, c):
        return self.__rmul__(c)
    
    def __eq__(self,p):
        return self.x==p.x and self.y==p.y
In [123]:
p1 = Pair(2,3)
In [124]:
p2 = Pair(1,4)
In [125]:
p1+p2
Out[125]:
Pair(3,7)
In [126]:
p1-p2
Out[126]:
Pair(1,-1)
In [127]:
p1-3
Out[127]:
Pair(-1,0)
In [128]:
p1 == p2
Out[128]:
False
In [129]:
p1 == p1
Out[129]:
True

[] operator

In [130]:
class Pair(object):
    def __init__(self, x, y):
        self.x = x
        self.y = y
        
    def __repr__(self):
        return 'Pair({0.x!r},{0.y!r})'.format(self)
    
    def __str__(self):
        return '({0.x!s},{0.y!s})'.format(self)
    
    def __getitem__(self, name):
        if name == "x":
            return self.x
        elif name == "y":
            return self.y
        
    def __setitem__(self, name, value):
        if name in ["x","y"]:
            self.__dict__[name] = value
        else:
            raise Exception("Only x,y values can be set")
In [132]:
p = Pair(2,3)
In [133]:
x = 2
In [134]:
p['x']
Out[134]:
2
In [135]:
p['y']
Out[135]:
3
In [136]:
p['x']
Out[136]:
2
In [137]:
p.x
Out[137]:
2
In [138]:
class UpperCase:
    def __getattr__(self, name):
        return name.upper()
In [139]:
u = UpperCase()
In [140]:
u.hello
Out[140]:
'HELLO'
In [141]:
u.python
Out[141]:
'PYTHON'
In [145]:
class Sealed:
    def __setattr__(self, name, value):
        raise Exception("No chance!")
In [146]:
s = Sealed()
In [147]:
s.x = 3
---------------------------------------------------------------------------
Exception                                 Traceback (most recent call last)
<ipython-input-147-442c8444ae31> in <module>()
----> 1 s.x = 3

<ipython-input-145-c14756ee149e> in __setattr__(self, name, value)
      1 class Sealed:
      2     def __setattr__(self, name, value):
----> 3         raise Exception("No chance!")

Exception: No chance!
In [152]:
class Date:
    __slots__ = ['year','month','day']
    
    def __init__(self, year, month, day):
        self.year = year
        self.month = month
        self.day = day
In [153]:
d = Date(2017,11,22)
In [156]:
d.x
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-156-1fbdfe908a1f> in <module>()
----> 1 d.x

AttributeError: 'Date' object has no attribute 'x'
In [157]:
d.y = 3
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-157-d9584a045fb4> in <module>()
----> 1 d.y = 3

AttributeError: 'Date' object has no attribute 'y'

calling functions from parent class

In [160]:
class Base:
    def __init__(self):
        print("Base.__init__")
        
class A(Base):
    def __init__(self):
        Base.__init__(self)
        print("A.__init__")
        
class B(Base):
    def __init__(self):
        Base.__init__(self)
        print("B.__init__")
        
class C(A,B):
    def __init__(self):
        A.__init__(self)
        B.__init__(self)
        print("C.__init__")
In [161]:
c = C()
Base.__init__
A.__init__
Base.__init__
B.__init__
C.__init__
In [184]:
class Base:
    def __init__(self):
        print("Base.__init__")
        
class A(Base):
    def __init__(self):
        super().__init__()
        #Base.__init__(self)
        print("A.__init__")
        
class B(Base):
    def __init__(self):
        #Base.__init__(self)
        super().__init__()
        self.value = 0
        print("B.__init__")
        
class C(B,A):
    def __init__(self):
        #A.__init__(self)
        #B.__init__(self)
        super().__init__()
        print("C.__init__")
In [185]:
c = C()
Base.__init__
A.__init__
B.__init__
C.__init__
In [171]:
C.__mro__
Out[171]:
(__main__.C, __main__.B, __main__.A, __main__.Base, object)
In [176]:
c.value
Out[176]:
0

problem Write a class Timer to measure time taken in a task. The class should have start and stop methods to start and stop timer. use time.time() to get timestamp at given instant. your class should work as given below

t = Timer()
t.start()
time.sleep(5)
t.stop()
print("Time taken:",t.get_time_taken())
In [190]:
import time

class Timer:
    
    def start(self):
        self.starttime = time.time()
    
    def stop(self):
        self.endtime = time.time()
        
    def get_time_taken(self):
        return self.endtime - self.starttime
    
t = Timer()
t.start()
for i in range(10000000):
    i*i*i
t.stop()
print("Time taken:", t.get_time_taken())
    
Time taken: 2.4421236515045166

context manager

In [191]:
with open("five.txt", "w") as f:
    f.write("six\n")
    
f.write("seven\n")
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-191-9983816653d9> in <module>()
      2     f.write("six\n")
      3 
----> 4 f.write("seven\n")

ValueError: I/O operation on closed file.
In [193]:
from socket import socket, AF_INET, SOCK_STREAM

class LazyConnection:
    def __init__(self, address, family=AF_INET, type_=SOCK_STREAM):
        self.address = address
        self.family = family
        self.type_ = type_
        self.sock = None
            
    def __enter__(self):
        print("Inside enter...")
        if self.sock is not None:
            raise RuntimeError("Socket already opened!")
        self.sock = socket(self.family, self.type_)
        self.sock.connect(self.address)
        return self.sock
    
    def __exit__(self, exeptn_type, exceptn_value, traceback):
        print("Inside exit...", exeptn_type, exceptn_value, traceback)
        self.sock.close()
        self.sock = None
In [198]:
from functools import partial
conn = LazyConnection(("www.python.org", 80))
  
with conn as s:
    s.send(b'GET /index.html HTTP/1.0\r\n')
    s.send(b'Host: www.python.org\r\n')
    s.send(b'\r\n')
    resp = b''.join(iter(partial(s.recv, 8192), b''))
    
print(resp.decode("utf-8"))
Inside enter...
Inside exit... None None None
HTTP/1.1 301 Moved Permanently
Server: Varnish
Retry-After: 0
Location: https://www.python.org/index.html
Content-Length: 0
Accept-Ranges: bytes
Date: Wed, 22 Nov 2017 09:17:01 GMT
Via: 1.1 varnish
Connection: close
X-Served-By: cache-sin18029-SIN
X-Cache: HIT
X-Cache-Hits: 0
X-Timer: S1511342221.200715,VS0,VE0
Strict-Transport-Security: max-age=63072000; includeSubDomains


problem Write a class ContextTimer which extends from our original class Timer. This new class should implement context management protocol. When you enter the with block timer should start. and when you exit with block timer should stop and print value of time taken for executing with block

with ContextTimer() as ct:
    for i in range(10000):
        for j in range(1000):
           s = 1*j*1.0

Time taken in with block: 2.12...

properties

In [199]:
class Person:
    def __init__(self, name):
        self._name = name
        
    def email(self):
        return self._name + "@vmware.com"
    
In [200]:
p = Person("alice")
In [201]:
p.email()
Out[201]:
'alice@vmware.com'
In [206]:
class Person:
    def __init__(self, name):
        self._name = name
        
    @property    
    def email(self):
        return self._name + "@vmware.com"
    
    @email.setter
    def email(self, value):
        raise Exception("Email can not be set")
    
    @email.deleter
    def email(self):
        raise Exception("Email can not be deleted")
In [207]:
p = Person("alice")
In [208]:
p.email
Out[208]:
'alice@vmware.com'
In [209]:
p.email= "alice@example.com"
---------------------------------------------------------------------------
Exception                                 Traceback (most recent call last)
<ipython-input-209-774d6b4ac397> in <module>()
----> 1 p.email= "alice@example.com"

<ipython-input-206-8933f1801563> in email(self, value)
      9     @email.setter
     10     def email(self, value):
---> 11         raise Exception("Email can not be set")
     12 
     13     @email.deleter

Exception: Email can not be set
In [210]:
p.email()
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-210-3e290d03dce3> in <module>()
----> 1 p.email()

TypeError: 'str' object is not callable
In [221]:
class Email:
    def __init__(self, name, domain):
        self.name = name
        self.domain = domain
        
    def email(self):
        return self.name + "@" + self.domain
    
    def __str__(self):
        return self.email()
    
    def __repr__(self):
        return "Email({0.name!r},vmware.com)".format(self)
        
class Person:
    def __init__(self, name):
        self._name = name
        
    @property    
    def email(self):
        return Email(self._name, "vmware.com")
    
    @email.setter
    def email(self, value):
        raise Exception("Email can not be set")
    
    @email.deleter
    def email(self):
        raise Exception("Email can not be deleted")
In [222]:
p = Person("alice")
In [223]:
p.email
Out[223]:
Email('alice',vmware.com)
In [224]:
print(p.email)
alice@vmware.com
In [225]:
str(p.email)
Out[225]:
'alice@vmware.com'
In [226]:
del p.email
---------------------------------------------------------------------------
Exception                                 Traceback (most recent call last)
<ipython-input-226-d5c698764d13> in <module>()
----> 1 del p.email

<ipython-input-221-bfc0dd1fba12> in email(self)
     27     @email.deleter
     28     def email(self):
---> 29         raise Exception("Email can not be deleted")

Exception: Email can not be deleted
In [227]:
p.email = Email("hello", "somedomain.com")
---------------------------------------------------------------------------
Exception                                 Traceback (most recent call last)
<ipython-input-227-2fc998c338a9> in <module>()
----> 1 p.email = Email("hello", "somedomain.com")

<ipython-input-221-bfc0dd1fba12> in email(self, value)
     23     @email.setter
     24     def email(self, value):
---> 25         raise Exception("Email can not be set")
     26 
     27     @email.deleter

Exception: Email can not be set

Desciptors

In [229]:
class Integer:
    def __init__(self, name):
        self.name = name
        
    def __get__(self, instance, cls):
        print("__get__ from",self)
        if instance is None:
            return self
        else:
            return instance.__dict__[self.name]
    
    def __set__(self, instance, value):
        print("__set__ from", self)
        if not isinstance(value, int):
            raise TypeError("Expected int")
        instance.__dict__[self.name] = value
        
    def __delete__(self, instance):
        print("__delete__ from", self)
        del instance.__dict__[self.name]
        
    def __str__(self):
        return "Integer<{0.name!s}>".format(self)
    
    def __repr__(self):
        return "Integer({0.name!r})".format(self)
In [230]:
class Point:
    x = Integer("x")
    y = Integer("y")
    
    def __init__(self, x, y):
        self.x = x
        self.y = y
In [231]:
p = Point(2,3)
__set__ from Integer<x>
__set__ from Integer<y>
In [232]:
p.x
__get__ from Integer<x>
Out[232]:
2
In [233]:
p.x = 3
__set__ from Integer<x>

Lets implement my_property using descriptor

In [235]:
class my_property:
    
    def __init__(self, func):
        self.func = func
        
    def __get__(self, instance, cls):
        if instance is None:
            return self
        print("my_property.__get__")
        return self.func(instance)
        
In [236]:
class Person:
    
    def __init__(self, name, email):
        self._name = name
        self._email = email
        
    @my_property
    def name(self):
        return self._name
In [237]:
p = Person("alice", "alice@example.com")
In [238]:
p.name
my_property.__get__
Out[238]:
'alice'

staticmethods and classmethods

In [239]:
from datetime import datetime
In [240]:
class MyDatetime(datetime):
    pass
In [241]:
datetime.now()
Out[241]:
datetime.datetime(2017, 11, 22, 15, 39, 23, 694740)
In [242]:
MyDatetime.now()
Out[242]:
MyDatetime(2017, 11, 22, 15, 39, 51, 960106)
In [246]:
class A:
    def __init__(self, x):
        self.x = x
        
    def __repr__(self):
        return "{0}({1})".format(self.__class__.__name__, repr(self.x))
    
    @staticmethod
    def parse1(value):
        return A(int(value))
    
    @classmethod
    def parse2(cls, value):
        return cls(value)
    
class B(A):
    pass
In [244]:
a = A.parse1("123")
In [245]:
a
Out[245]:
A(123)
In [247]:
b = B.parse1("123")
In [248]:
b
Out[248]:
A(123)
In [249]:
c = B.parse2("123")
In [250]:
c
Out[250]:
B('123')

Multithreading

In [255]:
%%file threads.py
import threading

import sys, time


def countdown():
    for i in reversed(range(10)):
        time.sleep(0.25)
    print("Finished: ", threading.currentThread().getName())
    
def main():
    n = int(sys.argv[1])
    threads = [threading.Thread(target=countdown) for i in range(n)]
    for t in threads:
        t.start()
    for t in threads:
        t.join()
        
if __name__ == "__main__":
    main()
Overwriting threads.py
In [257]:
!time -p python threads.py 10
Finished:  Thread-1
Finished:  Thread-6
Finished:  Thread-5
Finished:  Thread-8
Finished:  Thread-7
Finished:  Thread-2
Finished:  Thread-3
Finished:  Thread-4
Finished:  Thread-10
Finished:  Thread-9
real 2.58
user 0.07
sys 0.01
In [260]:
!seq 10 | xargs printf "http://httpbin.org/get?x=%d\n" >> urls.txt 
In [264]:
%%file sget.py
import sys
from urllib.request import urlopen

def get_urls(filename):
    return [line.strip() for line in open(filename)]

def wget(url):
    return urlopen(url).read()

def main():
    filename = sys.argv[1]
    for url in get_urls(filename):
        wget(url)
        
if __name__ == "__main__":
    main()
Overwriting sget.py
In [266]:
!time -p python sget.py urls.txt
real 13.49
user 0.16
sys 0.02
In [269]:
%%file pget.py
import sys
from sget import get_urls, wget
from multiprocessing.pool import ThreadPool

def main():
    filename = sys.argv[1]
    concurrency = int(sys.argv[2])
    urls = get_urls(filename)
    pool = ThreadPool(concurrency)
    pool.map(wget, urls)
    
if __name__ == "__main__":
    main()
Overwriting pget.py
In [270]:
!time -p python pget.py urls.txt 2
real 7.57
user 0.19
sys 0.00
In [272]:
!time -p python pget.py urls.txt 4
real 5.18
user 0.18
sys 0.02
In [274]:
%%file pcpu.py
import sys

from multiprocessing.pool import Pool

def task(dummy):
    s = 0
    for i in range(10000):
        for j in range(1000):
            s = s+i*j*1.0
    return s

def main():
    conc = int(sys.argv[1])
    pool = Pool(conc)
    pool.map(task, range(10))

if __name__ == "__main__":
    main()
Overwriting pcpu.py
In [275]:
!time -p python pcpu.py 1
real 17.15
user 17.14
sys 0.01
In [276]:
!time -p python pcpu.py 2
real 10.55
user 17.46
sys 0.01
In [277]:
!time -p python pcpu.py 4
real 11.26
user 33.13
sys 0.03
In [278]:
from threading import Event, Thread
In [280]:
def task(n , event):
    while (not event.is_set()) and n>0:
        print("T-minus", n)
        n -= 1
        time.sleep(5)
    print("Stopping, Bye!")
    
e = Event()
t = Thread(target=task, args=(10, e))
t.start()
T-minus 10
T-minus 9
T-minus 8
T-minus 7
T-minus 6
In [281]:
e.set()
Stopping, Bye!

References

google for

In [ ]: