You are on page 1of 66

PYTHON ADVANCED

PROGRAMMING

Chitra G M and P Rama Devi


Department of Computer Science Engineering
PYTHON ADVANCED
PROGRAMMING
Inter Process
Communication

Chitra G M and P Rama Devi


Department of Computer Science and Engineering
PYTHON ADVANCED PROGRAMMING
IPC

A process can be of two types:

Independent process.
Co-operating process.

An independent process is not affected by the execution of


other processes while a co-operating process can be
affected by other executing processes
PYTHON ADVANCED PROGRAMMING

Though one can think that those processes, which are running independently,
will execute very efficiently, in reality, there are many situations when co-
operative nature can be utilised for increasing computational speed,
convenience and modularity.

Inter process communication (IPC) is a mechanism which allows processes to


communicate with each other and synchronize their actions. The
communication between these processes can be seen as a method of co-
operation between them.

Processes can communicate with each other through both:


Shared Memory
Message passing
PYTHON ADVANCED PROGRAMMING

Consider the program

import multiprocessing
import time
result = []
def square_list(mylist):
global result
# append squares of mylist to global list result
for num in mylist:
result.append(num * num)
# print global list result
print("Result(in process p1)",result)
time.sleep(1)
PYTHON ADVANCED PROGRAMMING

if __name__ == "__main__":
# input list
mylist = [1,2,3,4]
# creating new process
p1 = multiprocessing.Process(target=square_list,
args=(mylist,))
# starting process
p1.start()
# wait until process is finished
p1.join()
# print global result list
print("Result(in main program)",result)
When the above program is executed the output is
available only in the childs address space.
So modify the above program such that the output is
available in both child and parents address space
PYTHON ADVANCED PROGRAMMING

import multiprocessing
def square_list(mylist, result, square_sum):
# append squares of mylist to result array
for idx, num in enumerate(mylist):
result[idx] = num * num
# square_sum value
square_sum.value = sum(result)

# print result Array


print("Result(in process p1):",result[:])
# print square_sum Value
print("Sum of squares(in process
p1):",square_sum.value)
PYTHON ADVANCED PROGRAMMING

if __name__ == "__main__":
# input list
mylist = [1,2,3,4]
# creating Array of int data type with space for 4 integers
result = multiprocessing.Array('i', 4)
# creating Value of int data type
square_sum = multiprocessing.Value('i')
# print(square_sum)
# creating new process
p1 = multiprocessing.Process(target=square_list, args=(mylist, result,
square_sum))
# starting process
p1.start()
# wait until process is finished
p1.join()
# print result array
print("Result(in main program):",result[:])
# print square_sum Value
print("Sum of squares(in main program):",square_sum.value)
THANK YOU

Chitra G M and P Rama Devi


Department of CSE
pramadevi@pes.edu
chitragm@pes.edu
PYTHON ADVANCED
PROGRAMMING

Chitra G M and P Rama Devi


Department of Computer Science Engineering
PYTHON ADVANCED
PROGRAMMING
Parallel Processes

Chitra G M and P Rama Devi


Department of Computer Science and Engineering
PYTHON ADVANCED PROGRAMMING
Parellel Processes

What is multiprocessing?

Multiprocessing refers to the ability of a system to support more


than one processor at the same time. Applications in a
multiprocessing system are broken to smaller routines that run
independently. The operating system allocates these threads to the
processors improving performance of the system.
PYTHON ADVANCED PROGRAMMING

Why multiprocessing?

Consider a computer system with a single processor. If it is assigned several


processes at the same time, it will have to interrupt each task and switch
briefly to another, to keep all of the processes going.
This situation is just like a chef working in a kitchen alone. He has to do
several tasks like baking, stirring, kneading dough, etc.
Multiprocessing: Running more than one process on a single processor
parallel processing: running a process on more than one processor.
PYTHON ADVANCED PROGRAMMING
Simple example for MultiProcessing

import multiprocessing
def print_cube(num):
print("Cube of a number is",num * num * num)
def print_square(num):
print("squre of a number is",num * num)
if __name__ == "__main__":
# creating processes
p1 = multiprocessing.Process(target=print_square, args=(10, ))
p2 = multiprocessing.Process(target=print_cube, args=(10, ))
# starting process 1
p1.start()
# starting process 2
p2.start()
# wait until process 1 is finished
p1.join()
# wait until process 2 is finished
p2.join()
# both processes finished
print("Done!")
PYTHON ADVANCED PROGRAMMING

# importing the multiprocessing module


import multiprocessing
import os
def f1():
print("p1_id: ",os.getpid())
def f2():
print("p2_id: ",os.getpid())
if __name__ == "__main__":
# printing main program process id
print("main process id",os.getpid())
# creating processes
p1 = multiprocessing.Process(target=f1)
p2 = multiprocessing.Process(target=f2)
PYTHON ADVANCED PROGRAMMING

# starting processes
p1.start()
p2.start()
# wait until processes are finished
p1.join()
p2.join()
# both processes finished
print("Both processes finished execution!")
# check if processes are alive
print("p1 status is alive?:",p1.is_alive())
print("p2 status is alive?:",p2.is_alive())
THANK YOU

Chitra G M and P Rama Devi


Department of CSE
pramadevi@pes.edu
chitragm@pes.edu
PYTHON ADVANCED
PROGRAMMING

Chitra G M and P Rama Devi


Department of Computer Science Engineering
PYTHON ADVANCED
PROGRAMMING
Parallel Processes

Chitra G M and P Rama Devi


Department of Computer Science and Engineering
PYTHON ADVANCED PROGRAMMING
Parellel Processes

What is multiprocessing?

Multiprocessing refers to the ability of a system to support more


than one processor at the same time. Applications in a
multiprocessing system are broken to smaller routines that run
independently. The operating system allocates these threads to the
processors improving performance of the system.
PYTHON ADVANCED PROGRAMMING

Why multiprocessing?

Consider a computer system with a single processor. If it is assigned several


processes at the same time, it will have to interrupt each task and switch
briefly to another, to keep all of the processes going.
This situation is just like a chef working in a kitchen alone. He has to do
several tasks like baking, stirring, kneading dough, etc.
Multiprocessing: Running more than one process on a single processor
parallel processing: running a process on more than one processor.
PYTHON ADVANCED PROGRAMMING
Simple example for MultiProcessing

import multiprocessing
def print_cube(num):
print("Cube of a number is",num * num * num)
def print_square(num):
print("squre of a number is",num * num)
if __name__ == "__main__":
# creating processes
p1 = multiprocessing.Process(target=print_square, args=(10, ))
p2 = multiprocessing.Process(target=print_cube, args=(10, ))
# starting process 1
p1.start()
# starting process 2
p2.start()
# wait until process 1 is finished
p1.join()
# wait until process 2 is finished
p2.join()
# both processes finished
print("Done!")
PYTHON ADVANCED PROGRAMMING

# importing the multiprocessing module


import multiprocessing
import os
def f1():
print("p1_id: ",os.getpid())
def f2():
print("p2_id: ",os.getpid())
if __name__ == "__main__":
# printing main program process id
print("main process id",os.getpid())
# creating processes
p1 = multiprocessing.Process(target=f1)
p2 = multiprocessing.Process(target=f2)
PYTHON ADVANCED PROGRAMMING

# starting processes
p1.start()
p2.start()
# wait until processes are finished
p1.join()
p2.join()
# both processes finished
print("Both processes finished execution!")
# check if processes are alive
print("p1 status is alive?:",p1.is_alive())
print("p2 status is alive?:",p2.is_alive())
THANK YOU

Chitra G M and P Rama Devi


Department of CSE
pramadevi@pes.edu
chitragm@pes.edu
PYTHON ADVANCED
PROGRAMMING

Chitra G M and P Rama Devi


Department of Computer Science Engineering
PYTHON ADVANCED
PROGRAMMING
Locks

Chitra G M and P Rama Devi


Department of Computer Science and Engineering
PYTHON ADVANCED PROGRAMMING
Race Condition

Race conditions and Locks

Multiprogramming and concurrency bring in the problem of


race conditions, where multiple processes executing
concurrently on shared data may leave the shared data in an
undesirable, inconsistent state due to concurrent execution.
Note that race conditions ca n happen even on a single
processor system, if processes are context switched out by
the scheduler, or are interrupted otherwise, while updating
shared data structures.
PYTHON ADVANCED PROGRAMMING

Consider a simple example of two processes of a process incrementing a


shared variable. Now, if the increments happen in parallel, it is possible that
the processes will overwrite each other’s result, and the counter will not be
incremented twice as expected. That is, a line of code that increments a
variable is not atomic, and can be executed concurrently by different threads.

ex. bank applications

• Pieces of code that must be accessed in a mutually exclusive atomic


manner by the contending processes are referred to as critical sections.
Critical sections must be protected with locks to guarantee the property of
mutual exclusion.

The code to update a shared counter is a simple example of a critical section.


PYTHON ADVANCED PROGRAMMING

Code that adds a new node to a linked list is another


example.

A critical section performs a certain operation on a shared


data structure, that may temporarily leave the data structure
in an inconsistent state in the middle of the operation.

Therefore, in order to maintain consistency and preserve the


invariants of shared data structures, critical sections must
always execute in a mutually exclusive fashion.

Locks guarantee that only one contending thread resides in


the critical section at any time, ensuring that the shared data
is not left in an inconsistent state.
PYTHON ADVANCED PROGRAMMING

#program to demonstrate race condition.


#Program to get letters in pairs
#remove Locks (demo race condition)
# execute the below program.

from threading import *


import random
import sys
import time
lock=Lock()
# get letters in pairs
PYTHON ADVANCED PROGRAMMING

def fn1() :
s = 'ABCDEFGH'
for i in range(0, len(s)) :
lock.acquire()
print(s[i], end=' ')
sys.stdout.flush()
time.sleep(int(random.random() * 3))
print(s[i], end=' ')
sys.stdout.flush()
lock.release()
time.sleep(int(random.random() * 3))
PYTHON ADVANCED PROGRAMMING

def fn2() :
s = 'abcdefgh'
for i in range(0, len(s)) :
lock.acquire()
print(s[i], end=' ')
sys.stdout.flush()
time.sleep(int(random.random() * 3))
print(s[i], end=' ')
sys.stdout.flush()
lock.release()
time.sleep(int(random.random() * 3))
THANK YOU

Chitra G M and P Rama Devi


Department of CSE
pramadevi@pes.edu
chitragm@pes.edu
PYTHON ADVANCED
PROGRAMMING

Chitra G M and P Rama Devi


Department of Computer Science Engineering
PYTHON ADVANCED
PROGRAMMING
Locks

Chitra G M and P Rama Devi


Department of Computer Science and Engineering
PYTHON ADVANCED PROGRAMMING
Race Condition

Race conditions and Locks

Multiprogramming and concurrency bring in the problem of


race conditions, where multiple processes executing
concurrently on shared data may leave the shared data in an
undesirable, inconsistent state due to concurrent execution.
Note that race conditions ca n happen even on a single
processor system, if processes are context switched out by
the scheduler, or are interrupted otherwise, while updating
shared data structures.
PYTHON ADVANCED PROGRAMMING

Consider a simple example of two processes of a process incrementing a


shared variable. Now, if the increments happen in parallel, it is possible that
the processes will overwrite each other’s result, and the counter will not be
incremented twice as expected. That is, a line of code that increments a
variable is not atomic, and can be executed concurrently by different threads.

ex. bank applications

• Pieces of code that must be accessed in a mutually exclusive atomic


manner by the contending processes are referred to as critical sections.
Critical sections must be protected with locks to guarantee the property of
mutual exclusion.

The code to update a shared counter is a simple example of a critical section.


PYTHON ADVANCED PROGRAMMING

Code that adds a new node to a linked list is another


example.

A critical section performs a certain operation on a shared


data structure, that may temporarily leave the data structure
in an inconsistent state in the middle of the operation.

Therefore, in order to maintain consistency and preserve the


invariants of shared data structures, critical sections must
always execute in a mutually exclusive fashion.

Locks guarantee that only one contending thread resides in


the critical section at any time, ensuring that the shared data
is not left in an inconsistent state.
PYTHON ADVANCED PROGRAMMING

#program to demonstrate race condition.


#Program to get letters in pairs
#remove Locks (demo race condition)
# execute the below program.

from threading import *


import random
import sys
import time
lock=Lock()
# get letters in pairs
PYTHON ADVANCED PROGRAMMING

def fn1() :
s = 'ABCDEFGH'
for i in range(0, len(s)) :
lock.acquire()
print(s[i], end=' ')
sys.stdout.flush()
time.sleep(int(random.random() * 3))
print(s[i], end=' ')
sys.stdout.flush()
lock.release()
time.sleep(int(random.random() * 3))
PYTHON ADVANCED PROGRAMMING

def fn2() :
s = 'abcdefgh'
for i in range(0, len(s)) :
lock.acquire()
print(s[i], end=' ')
sys.stdout.flush()
time.sleep(int(random.random() * 3))
print(s[i], end=' ')
sys.stdout.flush()
lock.release()
time.sleep(int(random.random() * 3))
THANK YOU

Chitra G M and P Rama Devi


Department of CSE
pramadevi@pes.edu
chitragm@pes.edu
PYTHON APPLICATION
PROGRAMMING

Chitra G M ,P Rama Devi


Computer Science and
Engineering
PYTHON APPLICATION PROGRAMMING

SQLite3

Chitra G M, P Rama Devi


Department of Computer Science and Engineering
PYTHON APPLICATION PROGRAMMING
Database Programming

SQLite3

• SQLite is a software library that implements a self-contained,


serverless, zero configuration, transactional SQL database
engine.

• SQLite is the most widely deployed SQL database engine . The


source code for SQLite is in the public domain.
PYTHON APPLICATION PROGRAMMING
Database Programming

SQLite3

SQLite is not directly comparable to client/server SQL database


engines such as MySQL, Oracle, PostgreSQL, or SQL Server since
SQLite is trying to solve a different problem.
PYTHON APPLICATION PROGRAMMING
Database Programming

Client Server DB Engine VS SQLite3

• Client/server SQL database engines strive to implement a


shared repository of enterprise data. They emphasize scalability,
concurrency, centralization, and control.

• SQLite strives to provide local data storage for individual


applications and devices.

• SQLite emphasizes economy, efficiency, reliability,


independence, and simplicity.
PYTHON APPLICATION PROGRAMMING
Database Programming

When not to Use SQLITE ?


Client/Server Applications
If there are many client programs sending SQL to the same
database over a network, then use a client/server database
engine instead of SQLite.
High-volume Websites
SQLite will normally work fine as the database backend to a
website. But if the website is write-intensive or is so busy that it
requires multiple servers, then consider using an enterprise-class
client/server database engine instead of SQLite.
PYTHON APPLICATION PROGRAMMING
Database Programming

When not to Use SQLITE ?


Very large datasets
An SQLite database is limited in size to 140 terabytes (247 bytes,
128 tibibytes).
High Concurrency
SQLite supports an unlimited number of simultaneous readers,
but it will only allow one writer at any instant in time.
PYTHON APPLICATION PROGRAMMING
Database Programming

When not to Use SQLITE ?


Very large datasets
An SQLite database is limited in size to 140 terabytes (247 bytes,
128 tibibytes).
High Concurrency
SQLite supports an unlimited number of simultaneous readers,
but it will only allow one writer at any instant in time.
PYTHON APPLICATION PROGRAMMING
Database Programming

Connection objects
Connection objects create a connection with the database and
these are further used for different transactions. These connection
objects are also used as representatives of the database session.
You can use a connection object for calling methods like commit(),
rollback() and close()

Cursor objects
Cursor is one of the powerful features of SQL. These are objects
that are responsible for submitting various SQL statements to a
database server.
PYTHON APPLICATION PROGRAMMING
Database Programming

Sample Program:
import sqlite3
cxn=sqlite3.connect("example.db")
cur=cxn.cursor()
''' #execute first and then comment
cur.execute('create table tab1 (name char(20), age integer)')
cur.execute('create table tab2 (name char(20), age integer)')
'''
PYTHON APPLICATION PROGRAMMING
Database Programming

Sample Program(continued):
cur.execute('insert into tab1 values ("chitra",34)')
cur.execute('insert into tab1 values ("rama",34)')
cxn.execute('insert into tab2 values ("Ganesh",21)')
cxn.execute('insert into tab2 values ("Ggg",21)')
#usage of place holder.
info=('aa',30)
cur.execute('insert into tab1 (name,age) values (?,?)',info)
x=cur.execute('select * from tab1')
for i in x:
print(i)
print("done")
THANK YOU

Chitra G M, Rama Devi


Department of Computer Science and Engineering

chitragm@pes.edu
+91 9900300411
pramadevi@pes.edu
+91 9620072112
PYTHON ADVANCED
PROGRAMMING

Chitra G M and P Rama Devi


Department of Computer Science Engineering
PYTHON ADVANCED
PROGRAMMING
Semaphores

Chitra G M and P Rama Devi


Department of Computer Science and Engineering
PYTHON ADVANCED PROGRAMMING
Semaphores

The Semaphore class of the Python threading module


implements the concept of semaphore.

It has a constructor and two methods acquire() and release().

The acquire() method decreases the semaphore count if the


count is greater than zero. Else it blocks till the count is
greater than zero.

The release() method increases the semaphore count and


wakes up one of the threads waiting on the semaphore.

Class semaphore([value])
The optional argument gives the initial value for the internal
counter; it defaults to 1.
PYTHON ADVANCED PROGRAMMING

acquire([blocking])

Acquire a semaphore.

When invoked without arguments: if the internal counter is larger than


zero on entry, decrement it by one and return immediately. If it is zero on
entry, block, waiting until some other thread has called release() to
make it larger than zero. This is done with proper interlocking so that if
multiple acquire() calls are blocked, release() will wake exactly one
of them up. The implementation may pick one at random, so the order in
which blocked threads are awakened should not be relied on. There is
no return value in this case.
PYTHON ADVANCED PROGRAMMING

When invoked with blocking set to true, do the same


thing as when called without arguments, and return
true. When invoked with blocking set to false, do not
block. If a call without an argument would block, return
false immediately; otherwise, do the same thing as
when called without arguments, and return true.

release()

Release a semaphore, incrementing the internal counter


by one. When it was zero on entry and another thread is
waiting for it to become larger than zero again, wake up
that thread.
PYTHON ADVANCED PROGRAMMING

import threading
from time import sleep
sem = threading.Semaphore()

def fun1():
print("fun1 starting")
sem.acquire()
for loop in range(1,5):
print("Fun1 Working in loop")
sleep(1)
sem.release()
print("fun1 finished")
PYTHON ADVANCED PROGRAMMING

def fun2():
print("fun2 starting")
while not sem.acquire(blocking=False):
print("Fun2 No Semaphore available")
sleep(1)
else:
print("Got Semphore")
for loop in range(1, 5):
print("Fun2 Working loop too")
sleep(1)
sem.release()
PYTHON ADVANCED PROGRAMMING

t1 = threading.Thread(target = fun1)
t2 = threading.Thread(target = fun2)
t1.start()
t2.start()
t1.join()
t2.join()
print("All Threads done Exiting")
PYTHON ADVANCED PROGRAMMING

# Then you do whatever sensitive thing needed to be


restricted to five threads.

# When you're finished, you release the semaphore, and it


goes back to 5.
s1.release()

# That's all fine, but you can also release it without acquiring
it first.
s1.release()

# The counter is now 6! That might make sense in some


situations, but not in most.
print(s1._value) # => 6

# If that doesn't make sense in your situation, use a


BoundedSemaphore.
PYTHON ADVANCED PROGRAMMING

s2 = BoundedSemaphore(5) # Start at 5.

s2.acquire() # Lower to 4.
s2.release() # Go back to 5.
print(s2._value)
try:
s2.release() # Try to raise to 6, above
starting value.
print(s2._value)
except ValueError:
print('As expected, it complained.')
THANK YOU

Chitra G M and P Rama Devi


Department of CSE
pramadevi@pes.edu
chitragm@pes.edu

You might also like