Python Training at VMWare Pune - Day 2

Sep 27-29, 2017 Vikrant Patil

These notes are available online at http://notes.pipal.in/2017/vmware-pune-advpy

© Pipal Academy LLP

Day 1 | Day 2 | Day 3

Problem: Write a module cmdline.py to build command-line application easily.

In [3]:
%%file commands.py
from cmdline import command, main

@command
def hello():
    """
    print hello
    """
    print("Hello world!")
    
@command
def cat(filename):
    """
    prints given file on standard output
    """
    for line in open(filename).readlines():
        print(line.strip())

@command        
def grep(word, filename):
    """
    greps given word in given file
    """
    for line in open(filename).readlines():
        if word in line:
            print(line.strip())
            
#grep("hello", "hello.py")
            
if __name__ == "__main__":
    main()
Overwriting commands.py

This is how it should work

$ python commands.py hello
Hello World!
$ python commands.py cat commands.py
from cmdline import command, main

@command
def hello():
    """
    print hello
    """
    print("Hello world!")

@command
def cat(filename):
    """
    prints given file on standard output
    """
    for line in open(filename).readlines():
        print(line.strip())

@command        
def grep(word, filename):
    """
    greps given word in given file
    """
    for line in open(filename).readlines():
        if word in line:
            print(line.strip())

if __name__ == "__main__":
    main()
In [12]:
%%file cmdline.py
import sys

commands = {}

def command(f):
    commands[f.__name__] = f
    return f

def help():
    print("Available command:")
    for cmd in commands.keys():
        print(cmd.ljust(10), commands[cmd].__doc__.strip())

def main():
    cmdname = sys.argv[1]
    args = sys.argv[2:]
    if "help" in sys.argv:
        help()
    elif cmdname in commands:
        func = commands[cmdname]
        print("Executing command:", cmdname)
        func(*args)
    
    
Overwriting cmdline.py
In [13]:
!python commands.py hello
Executing command: hello
Hello world!
In [14]:
!python commands.py cat commands.py
Executing command: cat
from cmdline import command, main

@command
def hello():
"""
print hello
"""
print("Hello world!")

@command
def cat(filename):
"""
prints given file on standard output
"""
for line in open(filename).readlines():
print(line.strip())

@command
def grep(word, filename):
"""
greps given word in given file
"""
for line in open(filename).readlines():
if word in line:
print(line.strip())

if __name__ == "__main__":
main()
In [15]:
!python commands.py grep hello commands.py
Executing command: grep
def hello():
print hello
In [16]:
!python commands.py help
Available command:
hello      print hello
cat        prints given file on standard output
grep       greps given word in given file

Decorators taking arguments

@with_retries(retries=3, delay=0.1)
wget(url
.
..

@debug(prefix="[INFO]: ")
def fib(n):


@login_required(role=admin)
def edit_interface(..):
.
.
In [30]:
import time

def with_retries(retries=5, delay=0):
    
    def decor(f):
        
        def g(*args):
            print("retries=", retries, "delay=",delay)
            for i in range(retries):
                try:
                    return f(*args)
                except Exception as e:
                    print(f.__name__, args, "failed", e)
                time.sleep(delay)
            print("Giving up!")
            
        return g
    
    return decor

from urllib.request import urlopen

@with_retries(retries=3, delay=0.5)
def wget(url):
    return urlopen(url).read()

def wget1(url):
    return urlopen(url).read()
In [23]:
wget("http://helloksdkjdshfkjhds.jhfjhd.com")
retries= 3 delay= 0.5
wget ('http://helloksdkjdshfkjhds.jhfjhd.com',) failed <urlopen error [Errno -2] Name or service not known>
wget ('http://helloksdkjdshfkjhds.jhfjhd.com',) failed <urlopen error [Errno -2] Name or service not known>
wget ('http://helloksdkjdshfkjhds.jhfjhd.com',) failed <urlopen error [Errno -2] Name or service not known>
Giving up!
In [27]:
decor = with_retries(retries=3, delay=0.4)
In [31]:
f = decor(wget1)
In [32]:
f("http://kjshadkjh.skjadh")
retries= 3 delay= 0.4
wget1 ('http://kjshadkjh.skjadh',) failed <urlopen error [Errno -2] Name or service not known>
wget1 ('http://kjshadkjh.skjadh',) failed <urlopen error [Errno -2] Name or service not known>
wget1 ('http://kjshadkjh.skjadh',) failed <urlopen error [Errno -2] Name or service not known>
Giving up!
In [33]:
from  functools import partial
In [34]:
def with_retries(f=None, retries=5, delay=0):
    if f == None:
        return partial(with_retries, retries=retries, delay=delay)
    
    def g(*args):
            print("retries=", retries, "delay=",delay)
            for i in range(retries):
                try:
                    return f(*args)
                except Exception as e:
                    print(f.__name__, args, "failed", e)
                time.sleep(delay)
            print("Giving up!")
    
    return g

More about decorators

In [35]:
def square(x):
    """
    compute square of a number
    """
    return x*x
In [36]:
help(square)
Help on function square in module __main__:

square(x)
    compute square of a number

In [37]:
!cat fib.py
import sys
from trace import trace

@trace
def fib(n):
    if n in [1, 2]:
        return 1
    else:
        return fib(n-1) + fib(n-2)
    
def main():
    n = int(sys.argv[1])
    fib(n)
    
if __name__ == "__main__":
    main()
In [38]:
from fib import fib
In [39]:
help(fib)
Help on function g in module trace:

g(*args)

In [40]:
print(fib)
<function trace.<locals>.g at 0x7f9d25990f28>
In [42]:
from functools import wraps

def debug(func):
    
    @wraps(func)
    def wrapper(*args):
        print("Debug: === ", func.__qualname__, args)
        return func(*args)
        
    return wrapper
In [43]:
@debug
def add(a, b):
    """
    adds a and b
    """
    return a+b
In [44]:
add(1,2)
Debug: ===  add (1, 2)
Out[44]:
3
In [45]:
help(add)
Help on function add in module __main__:

add(a, b)
    adds a and b

In [46]:
print(add)
<function add at 0x7f9d25989950>

Iterators and Generators

just observe the for loops in python

In [47]:
for n in [1,2, 3, 4, 5]:
    print(n)
1
2
3
4
5
In [48]:
for c in "string":
    print(c)
s
t
r
i
n
g
In [49]:
for key in {'x':1, 'y':2}:
    print(key)
x
y
In [50]:
%%file nums.txt
one
two
three
Writing nums.txt
In [53]:
for line in open("nums.txt"):
    print(repr(line))
'one\n'
'two\n'
'three'

The iteration protocol

In [61]:
items = [1, 2, 3]
In [62]:
itr = iter(items)
In [63]:
next(itr)
Out[63]:
1
In [64]:
next(itr)
Out[64]:
2
In [65]:
next(itr)
Out[65]:
3
In [66]:
next(itr)
---------------------------------------------------------------------------
StopIteration                             Traceback (most recent call last)
<ipython-input-66-94b7b2f7f392> in <module>()
----> 1 next(itr)

StopIteration: 

Generators

In [85]:
def square(numbers):
    for n in numbers:
        yield n*n
In [86]:
sq5 = square(range(1,6))
In [87]:
sq5
Out[87]:
<generator object square at 0x7f9d34046af0>
In [88]:
for s in sq5:
    print(s)
1
4
9
16
25
In [76]:
def squares(numbers):
    print("Begin squares")
    for n in numbers:
        print("computing square of", n)
        yield n*n
    print("Finish squares")
In [77]:
sq4 = squares(range(1, 5))
In [78]:
sq4
Out[78]:
<generator object squares at 0x7f9d3459a200>
In [79]:
next(sq4)
Begin squares
computing square of 1
Out[79]:
1
In [80]:
next(sq4)
computing square of 2
Out[80]:
4
In [82]:
next(sq4)
computing square of 3
Out[82]:
9
In [83]:
next(sq4)
computing square of 4
Out[83]:
16
In [84]:
next(sq4)
Finish squares
---------------------------------------------------------------------------
StopIteration                             Traceback (most recent call last)
<ipython-input-84-b9eab369b80c> in <module>()
----> 1 next(sq4)

StopIteration: 
In [89]:
for x in squares([1,2,3,4]):
    print(x)
Begin squares
computing square of 1
1
computing square of 2
4
computing square of 3
9
computing square of 4
16
Finish squares
In [90]:
a = squares(range(4))
In [91]:
b = a
In [92]:
next(a)
Begin squares
computing square of 0
Out[92]:
0
In [93]:
next(b)
computing square of 1
Out[93]:
1
In [94]:
x = squares(range(3))
In [95]:
y = squares(range(3))
In [96]:
next(x)
Begin squares
computing square of 0
Out[96]:
0
In [97]:
next(y)
Begin squares
computing square of 0
Out[97]:
0

problem: Write a generator countdown that takes number n as argument and generates all numbers down to 0.

>>> for i in countdown(3):
        print(i)
3
2
1
0

problem: Write a generator triangular that takes number n as argument and generates sequence of first n triangular numbers. nth triangular number is sum of first n natural numbers.

>>> for t in triangular(5):
        print(t)
1
3
6
10
15

Generator Expressions

In [98]:
[n*n for n in range(5)]
Out[98]:
[0, 1, 4, 9, 16]
In [99]:
(n*n for n in range(10))
Out[99]:
<generator object <genexpr> at 0x7f9d25997830>
In [100]:
sq = (n*n for n in range(10))
In [101]:
for s in sq:
    print(s)
0
1
4
9
16
25
36
49
64
81
In [102]:
sum((x*x for x in range(1000000)))
Out[102]:
333332833333500000
In [104]:
sum(x*x for x in range(1000000))
Out[104]:
333332833333500000
In [108]:
sum(list([x*x for x in range(100000)]))
Out[108]:
333328333350000

What is the advantage?

  • evaluation is lazy, that will give advantage while handling huge data
  • you can build lazy pipelines of data processing
  • and finally all complications are encapsulated inside generator and you get clean interface of iteration protocol.

Example: Building data pipelines

In [125]:
def integers():
    """
    lets generate infinite sequence of natural numbers
    """
    i = 1
    while True:
        yield i
        i += 1

def squares(numbers):
    for n in numbers:
        yield n*n
    #return (n*n for n in numbers)

def take(n , seq):
    it = iter(seq)
    return list(next(it) for i in range(n))
In [110]:
take(10, squares(integers()))
Out[110]:
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
In [111]:
import os
def find(root):
    for path, dirname, filenames in os.walk(root):
        for f in filenames:
            yield os.path.join(path, f)
In [112]:
def grep(pattern, seq):
    return (x for x in seq if pattern in x)
In [113]:
files = find(".")
pyfiles = grep(".py", files)
print(take(10, pyfiles))
['./sq1.py', './module.py', './trace.py', './fib.py', './test_weekday.py', './sq3.py', './fib2.py', './cmdline.py', './commands.py', './fib1.py']
In [114]:
def count(seq):
    i = 0
    for x in seq:
        i += 1
    return i
In [115]:
count([3,4,5,6,5])
Out[115]:
5
In [118]:
def count(seq):
    return sum(1 for x in seq)
In [119]:
count(range(100))
Out[119]:
100
In [120]:
files = find(".")
pyfiles = grep(".py", files)
print(count(pyfiles))
27
In [121]:
def readlines(filenames):
    """
    Returns an iterators over lines in all files specified
    """
    for f in filenames:
        for line in open(f):
            yield line

How many lines of python code we have written in this course?

In [123]:
files = find(".")
pyfiles = grep(".py", files)
lines = readlines(pyfiles)
print(count(lines))
245

How many function definations we have?

In [124]:
files = find(".")
pyfiles = grep(".py", files)
lines = readlines(pyfiles)
functions = grep("def", lines)
print(count(functions))
35

problem: Write a function get_paragraphs to split given text into paragraphs. The function should take a sequence of lines as argument and returns a sequence of paragraphs. Assume that there is an empty line after every paragraph

For sample input, see: (http://anandology.com/tmp/pg1342.txt) once the function is there , we should be able to find:

  • The numnber of paragraphs
  • the longest paragraph
In [129]:
files = find("/tmp/")
txtfiles = grep(".txt", files) # there is a huge file data.txt of size 5.4GB 
lines = readlines(txtfiles) # get stream of lines from that file
hellos = grep("hello", lines) # grep for hello in those lines
print(count(hellos))
3
In [130]:
def get_paragraphs(lines):
    paragraph = []
    for line in lines:
        if line.strip() != "":
            paragraph.append(line)
        elif paragraph:
            yield "".join(paragraph)
            paragraph = []
    
    if paragraph:
        yield "".join(paragraph)
In [131]:
lines = ["A1\n", "A2\n", "\n", "B1\n", "\n", "C1\n", "C2\n","C3\n"]
In [132]:
p = get_paragraphs(lines=lines)
In [133]:
next(p)
Out[133]:
'A1\nA2\n'
In [134]:
next(p)
Out[134]:
'B1\n'
In [135]:
next(p)
Out[135]:
'C1\nC2\nC3\n'
In [138]:
p1 = get_paragraphs(open("/tmp/pg1342.txt"))
In [139]:
max(p1, key=len)
Out[139]:
'"By this time, my dearest sister, you have received my hurried letter; I\nwish this may be more intelligible, but though not confined for time, my\nhead is so bewildered that I cannot answer for being coherent. Dearest\nLizzy, I hardly know what I would write, but I have bad news for you,\nand it cannot be delayed. Imprudent as the marriage between Mr. Wickham\nand our poor Lydia would be, we are now anxious to be assured it has\ntaken place, for there is but too much reason to fear they are not gone\nto Scotland. Colonel Forster came yesterday, having left Brighton the\nday before, not many hours after the express. Though Lydia\'s short\nletter to Mrs. F. gave them to understand that they were going to Gretna\nGreen, something was dropped by Denny expressing his belief that W.\nnever intended to go there, or to marry Lydia at all, which was\nrepeated to Colonel F., who, instantly taking the alarm, set off from B.\nintending to trace their route. He did trace them easily to Clapham,\nbut no further; for on entering that place, they removed into a hackney\ncoach, and dismissed the chaise that brought them from Epsom. All that\nis known after this is, that they were seen to continue the London road.\nI know not what to think. After making every possible inquiry on that\nside London, Colonel F. came on into Hertfordshire, anxiously renewing\nthem at all the turnpikes, and at the inns in Barnet and Hatfield, but\nwithout any success--no such people had been seen to pass through. With\nthe kindest concern he came on to Longbourn, and broke his apprehensions\nto us in a manner most creditable to his heart. I am sincerely grieved\nfor him and Mrs. F., but no one can throw any blame on them. Our\ndistress, my dear Lizzy, is very great. My father and mother believe the\nworst, but I cannot think so ill of him. Many circumstances might make\nit more eligible for them to be married privately in town than to pursue\ntheir first plan; and even if _he_ could form such a design against a\nyoung woman of Lydia\'s connections, which is not likely, can I suppose\nher so lost to everything? Impossible! I grieve to find, however, that\nColonel F. is not disposed to depend upon their marriage; he shook his\nhead when I expressed my hopes, and said he feared W. was not a man to\nbe trusted. My poor mother is really ill, and keeps her room. Could she\nexert herself, it would be better; but this is not to be expected. And\nas to my father, I never in my life saw him so affected. Poor Kitty has\nanger for having concealed their attachment; but as it was a matter of\nconfidence, one cannot wonder. I am truly glad, dearest Lizzy, that you\nhave been spared something of these distressing scenes; but now, as the\nfirst shock is over, shall I own that I long for your return? I am not\nso selfish, however, as to press for it, if inconvenient. Adieu! I\ntake up my pen again to do what I have just told you I would not; but\ncircumstances are such that I cannot help earnestly begging you all to\ncome here as soon as possible. I know my dear uncle and aunt so well,\nthat I am not afraid of requesting it, though I have still something\nmore to ask of the former. My father is going to London with Colonel\nForster instantly, to try to discover her. What he means to do I am sure\nI know not; but his excessive distress will not allow him to pursue any\nmeasure in the best and safest way, and Colonel Forster is obliged to\nbe at Brighton again to-morrow evening. In such an exigence, my\nuncle\'s advice and assistance would be everything in the world; he will\nimmediately comprehend what I must feel, and I rely upon his goodness."\n'
In [140]:
next(p1)
---------------------------------------------------------------------------
StopIteration                             Traceback (most recent call last)
<ipython-input-140-f727c5ce5803> in <module>()
----> 1 next(p1)

StopIteration: 
In [141]:
p2 = get_paragraphs(open("/tmp/pg1342.txt"))
In [142]:
count(p2)
Out[142]:
2189

Downloading stuff from web

In [143]:
from urllib.request import urlopen
In [144]:
response = urlopen("http://httpbin.org/html")
In [145]:
response
Out[145]:
<http.client.HTTPResponse at 0x7f9d3465ce48>
In [147]:
contents = response.read()
In [148]:
contents[:100]
Out[148]:
b'<!DOCTYPE html>\n<html>\n  <head>\n  </head>\n  <body>\n      <h1>Herman Melville - Moby-Dick</h1>\n\n     '
In [149]:
html = contents.decode("utf-8")
In [150]:
print(html[:400])
<!DOCTYPE html>
<html>
  <head>
  </head>
  <body>
      <h1>Herman Melville - Moby-Dick</h1>

      <div>
        <p>
          Availing himself of the mild, summer-cool weather that now reigned in these latitudes, and in preparation for the peculiarly active pursuits shortly to be anticipated, Perth, the begrimed, blistered old blacksmith, had not removed his portable forge to the hold again, af
In [151]:
response.status
Out[151]:
200

There is a third party library requests which makes handling http requests very handy

install it using

pip3 install reuest
In [152]:
import requests
In [153]:
response = requests.get("http://httpbin.org/html")
print(response.text[:400])
<!DOCTYPE html>
<html>
  <head>
  </head>
  <body>
      <h1>Herman Melville - Moby-Dick</h1>

      <div>
        <p>
          Availing himself of the mild, summer-cool weather that now reigned in these latitudes, and in preparation for the peculiarly active pursuits shortly to be anticipated, Perth, the begrimed, blistered old blacksmith, had not removed his portable forge to the hold again, af
In [154]:
response.headers
Out[154]:
{'Connection': 'keep-alive', 'Server': 'meinheld/0.6.1', 'Date': 'Thu, 28 Sep 2017 09:09:22 GMT', 'Content-Type': 'text/html; charset=utf-8', 'Content-Length': '3741', 'Access-Control-Allow-Origin': '*', 'Access-Control-Allow-Credentials': 'true', 'X-Powered-By': 'Flask', 'X-Processed-Time': '0.000546932220459', 'Via': '1.1 vegur'}
In [155]:
response.status_code
Out[155]:
200
In [160]:
response = requests.get("http://httpbin.org/get", params={"query":"python class", "page":"2"})
In [161]:
print(response.text)
{
  "args": {
    "page": "2", 
    "query": "python class"
  }, 
  "headers": {
    "Accept": "*/*", 
    "Accept-Encoding": "gzip, deflate", 
    "Connection": "close", 
    "Host": "httpbin.org", 
    "User-Agent": "python-requests/2.14.2"
  }, 
  "origin": "42.106.77.94", 
  "url": "http://httpbin.org/get?query=python+class&page=2"
}

In [162]:
response = requests.post("http://httpbin.org/post", data="Plain text data")
In [163]:
print(response.text)
{
  "args": {}, 
  "data": "Plain text data", 
  "files": {}, 
  "form": {}, 
  "headers": {
    "Accept": "*/*", 
    "Accept-Encoding": "gzip, deflate", 
    "Connection": "close", 
    "Content-Length": "15", 
    "Host": "httpbin.org", 
    "User-Agent": "python-requests/2.14.2"
  }, 
  "json": null, 
  "origin": "42.106.77.94", 
  "url": "http://httpbin.org/post"
}

In [164]:
response = requests.post("http://httpbin.org/post", data={"name":"Python", "date":"28th sep 2017"})
In [165]:
print(response.text)
{
  "args": {}, 
  "data": "", 
  "files": {}, 
  "form": {
    "date": "28th sep 2017", 
    "name": "Python"
  }, 
  "headers": {
    "Accept": "*/*", 
    "Accept-Encoding": "gzip, deflate", 
    "Connection": "close", 
    "Content-Length": "30", 
    "Content-Type": "application/x-www-form-urlencoded", 
    "Host": "httpbin.org", 
    "User-Agent": "python-requests/2.14.2"
  }, 
  "json": null, 
  "origin": "42.106.77.94", 
  "url": "http://httpbin.org/post"
}

In [166]:
import requests
url = "https://api.github.com/orgs/vmware/repos"
repos = requests.get(url).json()
In [167]:
type(repos)
Out[167]:
list
In [168]:
for repo in repos:
    print(repo["full_name"], repo['forks'])
vmware/pyvco 4
vmware/rvc 46
vmware/rbvmomi 151
vmware/vprobe-toolkit 8
vmware/CloudFS 15
vmware/vcd-nclient 2
vmware/lmock 5
vmware/FireBreath 2
vmware/weasel 1
vmware/vmware-vcenter 83
vmware/vmware-vshield 6
vmware/vcloud-rest 38
vmware/GemstoneWebTools 0
vmware/vmware-vcsa 17
vmware/vmware-vmware_lib 23
vmware/saml20serviceprovider 1
vmware/pg_rewind 19
vmware/vco-powershel-plugin 2
vmware/jenkins-reviewbot 12
vmware/dbeekeeper 0
vmware/thinapp_factory 16
vmware/vmware-cassandra 4
vmware/vmware-java 0
vmware/data-driven-framework 2
vmware/pyvmomi 421
vmware/pyvmomi-community-samples 358
vmware/open-vm-tools 133
vmware/pyvmomi-tools 18
vmware/upgrade-framework 11
vmware/webcommander 30
In [169]:
def get_forks(repo):
    return repo['forks']
repos = sorted(repos, key=get_forks, reverse=True)[:5]
In [170]:
for r in repos:
    print(r['full_name'], r['forks'])
vmware/pyvmomi 421
vmware/pyvmomi-community-samples 358
vmware/rbvmomi 151
vmware/open-vm-tools 133
vmware/vmware-vcenter 83
In [173]:
def get_top_contributors(reponame):
    url = "https://api.github.com/repos/{}/stats/contributors".format(reponame)
    print(url)
    contributors = requests.get(url).json()
    contributors = sorted(contributors, key=lambda x:x['total'], reverse=True)
    for c in contributors[:5]:
        print(c['author']['login'], c['total'])
    
In [174]:
get_top_contributors("vmware/pyvmomi")
https://api.github.com/repos/vmware/pyvmomi/stats/contributors
tianhao64 63
hartsock 54
michaelrice 10
wiggin15 7
mstagi 7

How to pass username and password?

username = "xxx"
passwd = open("somesecretfile").read().strip()
resp = requests.get(url, auth=(username, passwd))

Problem: How do you find distance between two cities using google

hints:

- url for map api is (https://maps.googleapis.com/maps/api/distancematrix/json)
- parameters for above get request are
        origins
        destinations
        units (metric)
In [180]:
import requests

def distance(origin, destination):
    url = "https://maps.googleapis.com/maps/api/distancematrix/json"
    response = requests.get(url, params={"units":"metric",
                                         "origins":origin,
                                         "destinations":destination
                                        })
    data = response.json()
    return data['rows'][0]['elements'][0]['distance']['text']
In [181]:
distance("pune", "dapoli")
Out[181]:
'189 km'

Multi-threading

In [182]:
%%file t1.py

import threading

def task():
    print("Hello ", threading.currentThread().getName())

def main():
    t1 = threading.Thread(target=task)
    t1.start()
    t1.join()
    
if __name__ == "__main__":
    main()
Writing t1.py
In [183]:
!python t1.py
Hello  Thread-1

Lets run it with 10 threads

In [184]:
%%file t2.py

import threading

def task():
    print("Hello ", threading.currentThread().getName())

def main():
    threads = [threading.Thread(target=task) for i in range(10)]
    
    for t in threads:
        t.start()
    
    for t in threads:
        t.join()
    
if __name__ == "__main__":
    main()
Writing t2.py
In [185]:
!python t2.py
Hello  Thread-1
Hello  Thread-2
Hello  Thread-3
Hello  Thread-4
Hello  Thread-5
Hello  Thread-6
Hello  Thread-7
Hello  Thread-8
Hello  Thread-9
Hello  Thread-10
In [186]:
%%file counter.py
import threading

class Counter:
    def __init__(self):
        self.count = 0
        
    def tick(self):
        self.count += 1
        

def task(counter, n):
    for i in range(n):
        counter.tick()
        
def main():
    counter = Counter()
    n = 100000
    nthreads = 10
    threads = [threading.Thread(target=task, args=(counter, n)) for i in range(nthreads)]
    
    for t in threads:
        t.start()
        
    for t in threads:
        t.join()
        
    print(counter.count)
    
if __name__ == "__main__":
    main()
    
Writing counter.py
In [187]:
!python counter.py
704070
In [188]:
!python counter.py
647723
In [192]:
!time -p python counter.py
487862
real 0.48
user 0.48
sys 0.00
In [190]:
%%file counter2.py
import threading

class Counter:
    def __init__(self):
        self.count = 0
        self.lock = threading.Lock()
        
    def tick(self):
        with self.lock:
            self.count += 1
        

def task(counter, n):
    for i in range(n):
        counter.tick()
        
def main():
    counter = Counter()
    n = 100000
    nthreads = 10
    threads = [threading.Thread(target=task, args=(counter, n)) for i in range(nthreads)]
    
    for t in threads:
        t.start()
        
    for t in threads:
        t.join()
        
    print(counter.count)
    
if __name__ == "__main__":
    main()
    
Writing counter2.py
In [191]:
!python counter2.py
1000000
In [193]:
!time -p python counter2.py
1000000
real 4.49
user 3.98
sys 3.48
In [194]:
!time -p python counter.py
723974
real 0.52
user 0.51
sys 0.00
In [195]:
!seq 10 | xargs printf "http://httpbin.org/get?x=%d\n"
http://httpbin.org/get?x=1
http://httpbin.org/get?x=2
http://httpbin.org/get?x=3
http://httpbin.org/get?x=4
http://httpbin.org/get?x=5
http://httpbin.org/get?x=6
http://httpbin.org/get?x=7
http://httpbin.org/get?x=8
http://httpbin.org/get?x=9
http://httpbin.org/get?x=10
In [196]:
!seq 10 | xargs printf "http://httpbin.org/get?x=%d\n" >urls.txt
In [197]:
%%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()
Writing sget.py
In [199]:
!time -p python sget.py urls.txt
real 14.94
user 0.16
sys 0.01
In [200]:
%%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()
Writing pget.py
In [201]:
!time -p python pget.py urls.txt 1
real 12.59
user 0.19
sys 0.01
In [202]:
!time -p python pget.py urls.txt 2
real 7.46
user 0.16
sys 0.02
In [203]:
!time -p python pget.py urls.txt 4
real 4.66
user 0.17
sys 0.02
In [204]:
!time -p python pget.py urls.txt 8
real 3.05
user 0.17
sys 0.01
In [205]:
import sget
In [206]:
get_urls
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
<ipython-input-206-fd6e8bad1852> in <module>()
----> 1 get_urls

NameError: name 'get_urls' is not defined
In [207]:
sget.get_urls
Out[207]:
<function sget.get_urls>
In [208]:
sget.wget
Out[208]:
<function sget.wget>
In [209]:
from sget import get_urls
In [210]:
get_urls
Out[210]:
<function sget.get_urls>
In [219]:
%%file pcpu.py

import sys

from multiprocessing.pool import ThreadPool

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

def main():
    concurrency = int(sys.argv[1])
    pool = ThreadPool(concurrency)
    pool.map(task, range(10))
    
if __name__ == "__main__":
    main()
Overwriting pcpu.py
In [214]:
!time -p python pcpu.py 1
real 14.28
user 14.23
sys 0.01
In [215]:
!time -p python pcpu.py 2
real 14.35
user 14.35
sys 0.01
In [216]:
!time -p python pcpu.py 4
real 15.30
user 15.20
sys 0.11
In [223]:
%%file pcpu1.py

import sys

from multiprocessing.pool import Pool

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

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

def main():
    concurrency = int(sys.argv[1])
    pool = Pool(concurrency)
    pool.map(task, range(10))
    pool.map(task2, range(10))
    
    
if __name__ == "__main__":
    main()
Overwriting pcpu1.py
In [220]:
!time -p python pcpu1.py 1
real 14.40
user 14.34
sys 0.03
In [224]:
!time -p python pcpu1.py 2
real 17.11
user 28.55
sys 0.01
In [222]:
!time -p python pcpu1.py 4
real 8.52
user 28.69
sys 0.01

Refernce: google for Concurrency from Ground up - video by David Beazley

String formatting

In [225]:
"Wizard of oz is {}".format("python")
Out[225]:
'Wizard of oz is python'
In [226]:
"wizard of {} is in {}".format("python", "oz")
Out[226]:
'wizard of python is in oz'
In [227]:
"purpose of life is {0}, my compuation in {1} says so!".format(42, "python")
Out[227]:
'purpose of life is 42, my compuation in python says so!'
In [230]:
for i in range(1, 11):
    line = "{0:2d} {1:3d} {2:4d}".format(i, i*i, i*i*i)
    print(line)
 1   1    1
 2   4    8
 3   9   27
 4  16   64
 5  25  125
 6  36  216
 7  49  343
 8  64  512
 9  81  729
10 100 1000
In [231]:
for i in range(1, 11):
    line = "{ints:2d} {sqrs:3d} {cubes:4d}".format(ints=i, sqrs=i*i, cubes=i*i*i)
    print(line)
 1   1    1
 2   4    8
 3   9   27
 4  16   64
 5  25  125
 6  36  216
 7  49  343
 8  64  512
 9  81  729
10 100 1000
In [232]:
"12".zfill(10)
Out[232]:
'0000000012'
In [233]:
"12.25".zfill(10)
Out[233]:
'0000012.25'
In [234]:
"center".center(50)
Out[234]:
'                      center                      '
In [235]:
"center".rjust(50)
Out[235]:
'                                            center'
In [236]:
"center".ljust(50)
Out[236]:
'center                                            '
  • Write a fucntion pascal to generate pascal triangle of base n.
      >>> pascal(3)
      [[1],[1,1],[1,2,1]]
  • Write a functions print_pascal to prety print pascal triangle as shown below
      >>> print_pascal(5)
          1
         1 1
        1 2 1
       1 3 3 1
      1 4 6 4 1