Author: Saim Khalid

  • math Module

    Python math Module

    The math module is a built-in module in Python that is used for performing mathematical operations. This module provides various built-in methods for performing different mathematical tasks.

    Note: The math module’s methods do not work with complex numbers. For that, you can use the cmath module.

    Importing math Module

    Before using the methods of the math module, you need to import the mathmodule into your code. The following is the syntax:

    import math
    

    Methods of Python math Module

    The following is the list of math module methods that we have categorized based on their functionality and usage.

    Math Module – Theoretic and Representation Methods

    Python includes following theoretic and representation Functions in the mathmodule −

    Sr.No.Function & Description
    1math.ceil(x)The ceiling of x: the smallest integer not less than x
    2math.comb(n,k)This function is used to find the returns the number of ways to choose “x” items from “y” items without repetition and without order.
    3math.copysign(x, y)This function returns a float with the magnitude (absolute value) of x but the sign of y.
    4math.cmp(x, y)This function is used to compare the values of to objects. This function is deprecated in Python3.
    5math.fabs(x)This function is used to calculate the absolute value of a given integer.
    6math.factorial(n)This function is used to find the factorial of a given integer.
    7math.floor(x)This function calculates the floor value of a given integer.
    8math.fmod(x, y)The fmod() function in math module returns same result as the “%”operator. However fmod() gives more accurate result of modulo division than modulo operator.
    9math.frexp(x)This function is used to calculate the mantissa and exponent of a given number.
    10math.fsum(iterable)This function returns the floating point sum of all numeric items in an iterable i.e. list, tuple, array.
    11math.gcd(*integers)This function is used to calculate the greatest common divisor of all the given integers.
    12math.isclose()This function is used to determine whether two given numeric values are close to each other.
    13math.isfinite(x)This function is used to determine whether the given number is a finite number.
    14math.isinf(x)This function is used to determine whether the given value is infinity (+ve or, -ve).
    15math.isnan(x)This function is used to determine whether the given number is “NaN”.
    16math.isqrt(n)This function calculates the integer square-root of the given non negative integer.
    17math.lcm(*integers)This function is used to calculate the least common factor of the given integer arguments.
    18math.ldexp(x, i)This function returns product of first number with exponent of second number. So, ldexp(x,y) returns x*2**y. This is inverse of frexp() function.
    19math.modf(x)This returns the fractional and integer parts of x in a two-item tuple.
    20math.nextafter(x, y, steps)This function returns the next floating-point value after x towards y.
    21math.perm(n, k)This function is used to calculate the permutation. It returns the number of ways to choose x items from y items without repetition and with order.
    22math.prod(iterable, *, start)This function is used to calculate the product of all numeric items in the iterable (list, tuple) given as argument.
    23math.remainder(x,y)This function returns the remainder of x with respect to y. This is the difference x − n*y, where n is the integer closest to the quotient x / y.
    24math.trunc(x)This function returns integral part of the number, removing the fractional part. trunc() is equivalent to floor() for positive x, and equivalent to ceil() for negative x.
    25math.ulp(x)This function returns the value of the least significant bit of the float x. trunc() is equivalent to floor() for positive x, and equivalent to ceil() for negative x.

    Math Module – Power and Logarithmic Methods

    Sr.No.Function & Description
    1math.cbrt(x)This function is used to calculate the cube root of a number.
    2math.exp(x)This function calculate the exponential of x: ex
    3math.exp2(x)This function returns 2 raised to power x. It is equivalent to 2**x.
    4math.expm1(x)This function returns e raised to the power x, minus 1. Here e is the base of natural logarithms.
    5math.log(x)This function calculates the natural logarithm of x, for x> 0.
    6math.log1p(x)This function returns the natural logarithm of 1+x (base e). The result is calculated in a way which is accurate for x near zero.
    7math.log2(x)This function returns the base-2 logarithm of x. This is usually more accurate than log(x, 2).
    8math.log10(x)The base-10 logarithm of x for x> 0.
    9math.pow(x, y)The value of x**y.
    10math.sqrt(x)The square root of x for x > 0

    Math Module – Trigonometric Methods

    Python includes following functions that perform trigonometric calculations in the math module −

    Sr.No.Function & Description
    1math.acos(x)This function returns the arc cosine of x, in radians.
    2math.asin(x)This function returns the arc sine of x, in radians.
    3math.atan(x)This function returns the arc tangent of x, in radians.
    4math.atan2(y, x)This function returns atan(y / x), in radians.
    5math.cos(x)This function returns the cosine of x radians.
    6math.sin(x)This function returns the sine of x radians.
    7math.tan(x)This function returns the tangent of x radians.
    8math.hypot(x, y)This function returns the Euclidean norm, sqrt(x*x + y*y).

    Math Module – Angular conversion Methods

    Following are the angular conversion function provided by Python math module −

    Sr.No.Function & Description
    1math.degrees(x)This function converts the given angle from radians to degrees.
    2math.radians(x)This function converts the given angle from degrees to radians.

    Math Module – Mathematical Constants

    The Python math module defines the following mathematical constants −

    Sr.No.Constants & Description
    1math.piThis represents the mathematical constant pi, which equals to “3.141592…” to available precision.
    2math.eThis represents the mathematical constant e, which is equal to “2.718281…” to available precision.
    3math.tauThis represents the mathematical constant Tau (denoted by ). It is equivalent to the ratio of circumference to radius, and is equal to 2.
    4math.infThis represents positive infinity. For negative infinity use “−math.inf”.
    5math.nanThis constant is a floating-point “not a number” (NaN) value. Its value is equivalent to the output of float(‘nan’).

    Math Module – Hyperbolic Methods

    Hyperbolic functions are analogs of trigonometric functions that are based on hyperbolas instead of circles. Following are the hyperbolic functions of the Python math module −

    Sr.No.Function & Description
    1math.acosh(x)This function is used to calculate the inverse hyperbolic cosine of the given value.
    2math.asinh(x)This function is used to calculate the inverse hyperbolic sine of a given number.
    3math.atanh(x)This function is used to calculate the inverse hyperbolic tangent of a number.
    4math.cosh(x)This function is used to calculate the hyperbolic cosine of the given value.
    5math.sinh(x)This function is used to calculate the hyperbolic sine of a given number.
    6math.tanh(x)This function is used to calculate the hyperbolic tangent of a number.

    Math Module – Special Methods

    Following are the special functions provided by the Python math module −

    Sr.No.Function & Description
    1math.erf(x)This function returns the value of the Gauss error function for the given parameter.
    2math.erfc(x)This function is the complementary for the error function. Value of erf(x) is equivalent to 1-erf(x).
    3math.gamma(x)This is used to calculate the factorial of the complex numbers. It is defined for all the complex numbers except the non-positive integers.
    4math.lgamma(x)This function is used to calculate the natural logarithm of the absolute value of the Gamma function at x.

    Example Usage

    The following example demonstrates the use of math module and its methods:

    # Importing math Moduleimport math
    
    # Using methods of math moduleprint(math.sqrt(9))print(math.pow(3,3))print(math.exp(1))print(math.log(100,10))print(math.factorial(4))print(math.gcd(12,3))

    Output

    3.0
    27.0
    2.718281828459045
    2.0
    24
    3
    
  • Date and Time

    A Python program can handle date and time in several ways. Converting between date formats is a common chore for computers. Following modules in Python’s standard library handle date and time related processing −

    • DateTime module
    • Time module
    • Calendar module

    What are Tick Intervals

    Time intervals are floating-point numbers in units of seconds. Particular instants in time are expressed in seconds since 12:00am, January 1, 1970(epoch).

    There is a popular time module available in Python, which provides functions for working with times, and for converting between representations. The function time.time() returns the current system time in ticks since 12:00am, January 1, 1970(epoch).

    Example

    import time # This is required to include time module.
    ticks = time.time()print("Number of ticks since 12:00am, January 1, 1970:", ticks)

    This would produce a result something as follows −

    Number of ticks since 12:00am, January 1, 1970: 1681928297.5316436
    

    Date arithmetic is easy to do with ticks. However, dates before the epoch cannot be represented in this form. Dates in the far future also cannot be represented this way – the cutoff point is sometime in 2038 for UNIX and Windows.

    What is TimeTuple?

    Many of the Python’s time functions handle time as a tuple of 9 numbers, as shown below −

    IndexFieldValues
    04-digit year2016
    1Month1 to 12
    2Day1 to 31
    3Hour0 to 23
    4Minute0 to 59
    5Second0 to 61 (60 or 61 are leap-seconds)
    6Day of Week0 to 6 (0 is Monday)
    7Day of year1 to 366 (Julian day)
    8Daylight savings-1, 0, 1, -1 means library determines DST

    For example,

    >>>import time
    >>>print(time.localtime())

    This would produce an output as follows −

    time.struct_time(tm_year=2023, tm_mon=4, tm_mday=19, tm_hour=23, tm_min=49, tm_sec=8, tm_wday=2, tm_yday=109, tm_isdst=0)
    

    The above tuple is equivalent to struct_time structure. This structure has the following attributes −

    IndexAttributesValues
    0tm_year2016
    1tm_mon1 to 12
    2tm_mday1 to 31
    3tm_hour0 to 23
    4tm_min0 to 59
    5tm_sec0 to 61 (60 or 61 are leap-seconds)
    6tm_wday0 to 6 (0 is Monday)
    7tm_yday1 to 366 (Julian day)
    8tm_isdst-1, 0, 1, -1 means library determines DST

    Getting the Current Time

    To translate a time instant from seconds since the epoch floating-point value into a time-tuple, pass the floating-point value to a function (e.g., localtime) that returns a time-tuple with all valid nine items.

    import time
    localtime = time.localtime(time.time())print("Local current time :", localtime)

    This would produce the following result, which could be formatted in any other presentable form −

    Local current time : time.struct_time(tm_year=2023, tm_mon=4, tm_mday=19, tm_hour=23, tm_min=42, tm_sec=41, tm_wday=2, tm_yday=109, tm_isdst=0)
    

    Getting the Formatted Time

    You can format any time as per your requirement, but a simple method to get time in a readable format is asctime() −

    import time
    
    localtime = time.asctime( time.localtime(time.time()))print("Local current time :", localtime)

    This would produce the following output −

    Local current time : Wed Apr 19 23:45:27 2023
    

    Getting the Calendar for a Month

    The calendar module gives a wide range of methods to play with yearly and monthly calendars. Here, we print a calendar for a given month (Jan 2008).

    import calendar
    cal = calendar.month(2023,4)print("Here is the calendar:")print(cal)

    This would produce the following output −

    Here is the calendar:
    
     April 2023
    Mo Tu We Th Fr Sa Su
                1  2
    3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30

    The time Module

    There is a popular time module available in Python, which provides functions for working with times and for converting between representations. Here is the list of all available methods.

    Sr.No.Function with Description
    1time.altzoneThe offset of the local DST timezone, in seconds west of UTC, if one is defined. This is negative if the local DST timezone is east of UTC (as in Western Europe, including the UK). Only use this if daylight is nonzero.
    2time.asctime([tupletime])Accepts a time-tuple and returns a readable 24-character string such as ‘Tue Dec 11 18:07:14 2008’.
    3time.clock( )Returns the current CPU time as a floating-point number of seconds. To measure computational costs of different approaches, the value of time.clock is more useful than that of time.time().
    4time.ctime([secs])Like asctime(localtime(secs)) and without arguments is like asctime( )
    5time.gmtime([secs])Accepts an instant expressed in seconds since the epoch and returns a time-tuple t with the UTC time. Note : t.tm_isdst is always 0
    6time.localtime([secs])Accepts an instant expressed in seconds since the epoch and returns a time-tuple t with the local time (t.tm_isdst is 0 or 1, depending on whether DST applies to instant secs by local rules).
    7time.mktime(tupletime)Accepts an instant expressed as a time-tuple in local time and returns a floating-point value with the instant expressed in seconds since the epoch.
    8time.sleep(secs)Suspends the calling thread for secs seconds.
    9time.strftime(fmt[,tupletime])Accepts an instant expressed as a time-tuple in local time and returns a string representing the instant as specified by string fmt.
    10time.strptime(str,fmt=’%a %b %d %H:%M:%S %Y’)Parses str according to format string fmt and returns the instant in time-tuple format.
    11time.time( )Returns the current time instant, a floating-point number of seconds since the epoch.
    12time.tzset()Resets the time conversion rules used by the library routines. The environment variable TZ specifies how this is done.

    Let us go through the functions briefly.

    There are two important attributes available with time module. They are −

    Sr.No.Attribute with Description
    1time.timezoneAttribute time.timezone is the offset in seconds of the local time zone (without DST) from UTC (>0 in the Americas; <=0 in most of Europe, Asia, Africa).
    2time.tznameAttribute time.tzname is a pair of locale-dependent strings, which are the names of the local time zone without and with DST, respectively.

    The calendar Module

    The calendar module supplies calendar-related functions, including functions to print a text calendar for a given month or year.

    By default, calendar takes Monday as the first day of the week and Sunday as the last one. To change this, call the calendar.setfirstweekday() function.

    Here is a list of functions available with the calendar module −

    Sr.No.Function with Description
    1calendar.calendar()Returns a multi-line string with a calendar for year year formatted into three columns separated by c spaces. w is the width in characters of each date; each line has length 21*w+18+2*c. l is the number of lines for each week.
    2calendar.firstweekday()Returns the current setting for the weekday that starts each week. By default, when calendar is first imported, this is 0, meaning Monday.
    3calendar.isleap()Returns True if year is a leap year; otherwise, False.
    4calendar.leapdays()Returns the total number of leap days in the years within range(y1,y2).
    5calendar.month()Returns a multi-line string with a calendar for month month of year year, one line per week plus two header lines. w is the width in characters of each date; each line has length 7*w+6. l is the number of lines for each week.
    6calendar.monthcalendar()Returns a list of lists of ints. Each sublist denotes a week. Days outside month month of year year are set to 0; days within the month are set to their day-of-month, 1 and up.
    7calendar.monthrange()Returns two integers. The first one is the code of the weekday for the first day of the month month in year year; the second one is the number of days in the month. Weekday codes are 0 (Monday) to 6 (Sunday); month numbers are 1 to 12.
    8calendar.prcal()Like print calendar.calendar(year,w,l,c).
    9calendar.prmonth()Like print calendar.month(year,month,w,l).
    10calendar.setfirstweekday()Sets the first day of each week to weekday code weekday. Weekday codes are 0 (Monday) to 6 (Sunday).
    11calendar.timegm()The inverse of time.gmtime: accepts a time instant in time-tuple form and returns the same instant as a floating-point number of seconds since the epoch.
    12calendar.weekday()Returns the weekday code for the given date. Weekday codes are 0 (Monday) to 6 (Sunday); month numbers are 1 (January) to 12 (December).

    Python datetime Module

    Python’s datetime module is included in the standard library. It consists of classes that help manipulate data and time data and perform date time arithmetic.

    Objects of datetime classes are either aware or nave. If the object includes timezone information it is aware, and if not it is classified as nave. An object of date class is nave, whereas time and datetime objects are aware.

    Python date Object

    A date object represents a date with year, month, and day. The current Gregorian calendar is indefinitely extended in both directions.

    Syntax

    datetime.date(year, month, day)

    Arguments must be integers, in the following ranges −

    • year − MINYEAR <= year <= MAXYEAR
    • month − 1 <= month <= 12
    • day − 1 <= day <= number of days in the given month and year

    If the value of any argument outside those ranges is given, ValueError is raised.

    Example

    from datetime import date
    date1 = date(2023,4,19)print("Date:", date1)
    date2 = date(2023,4,31)

    It will produce the following output −

    Date: 2023-04-19
    Traceback (most recent call last):
     File "C:\Python311\hello.py", line 8, in <module>
      date2 = date(2023, 4, 31)
    ValueError: day is out of range for month
    

    date class attributes

    • date.min − The earliest representable date, date(MINYEAR, 1, 1).
    • date.max − The latest representable date, date(MAXYEAR, 12, 31).
    • date.resolution − The smallest possible difference between non-equal date objects.
    • date.year − Between MINYEAR and MAXYEAR inclusive.
    • date.month − Between 1 and 12 inclusive.
    • date.day − Between 1 and the number of days in the given month of the given year.

    Example

    from datetime import date
    
    # Getting min date
    mindate = date.minprint("Minimum Date:", mindate)# Getting max date
    maxdate = date.maxprint("Maximum Date:", maxdate)
    
    Date1 = date(2023,4,20)print("Year:", Date1.year)print("Month:", Date1.month)print("Day:", Date1.day)

    It will produce the following output −

    Minimum Date: 0001-01-01
    Maximum Date: 9999-12-31
    Year: 2023
    Month: 4
    Day: 20
    

    Class Methods in Date Class

    • today() − Return the current local date.
    • fromtimestamp(timestamp) − Return the local date corresponding to the POSIX timestamp, such as is returned by time.time().
    • fromordinal(ordinal) − Return the date corresponding to the proleptic Gregorian ordinal, where January 1 of year 1 has ordinal 1.
    • fromisoformat(date_string) − Return a date corresponding to a date_string given in any valid ISO 8601 format, except ordinal dates

    Example

    from datetime import date
    
    print(date.today())
    d1=date.fromisoformat('2023-04-20')print(d1)
    d2=date.fromisoformat('20230420')print(d2)
    d3=date.fromisoformat('2023-W16-4')print(d3)

    It will produce the following output −

    2023-04-20
    2023-04-20
    2023-04-20
    2023-04-20
    

    Instance Methods in Date Class

    • replace() − Return a date by replacing specified attributes with new values by keyword arguments are specified.
    • timetuple() − Return a time.struct_time such as returned by time.localtime().
    • toordinal() − Return the proleptic Gregorian ordinal of the date, where January 1 of year 1 has ordinal 1. For any date object d, date.fromordinal(d.toordinal()) == d.
    • weekday() − Return the day of the week as an integer, where Monday is 0 and Sunday is 6.
    • isoweekday() − Return the day of the week as an integer, where Monday is 1 and Sunday is 7.
    • isocalendar() − Return a named tuple object with three components: year, week and weekday.
    • isoformat() − Return a string representing the date in ISO 8601 format, YYYY-MM-DD:
    • __str__() − For a date d, str(d) is equivalent to d.isoformat()
    • ctime() − Return a string representing the date:
    • strftime(format) − Return a string representing the date, controlled by an explicit format string.
    • __format__(format) − Same as date.strftime().

    Example

    from datetime import date
    d = date.fromordinal(738630)# 738630th day after 1. 1. 0001print(d)print(d.timetuple())# Methods related to formatting string outputprint(d.isoformat())print(d.strftime("%d/%m/%y"))print(d.strftime("%A %d. %B %Y"))print(d.ctime())print('The {1} is {0:%d}, the {2} is {0:%B}.'.format(d,"day","month"))# Methods for to extracting 'components' under different calendars
    t = d.timetuple()for i in t:print(i)
       
    ic = d.isocalendar()for i in ic:print(i)# A date object is immutable; all operations produce a new objectprint(d.replace(month=5))

    It will produce the following output −

    2023-04-20
    time.struct_time(tm_year=2023, tm_mon=4, tm_mday=20, tm_hour=0, tm_min=0, tm_sec=0, tm_wday=3, tm_yday=110, tm_isdst=-1)
    2023-04-20
    20/04/23
    Thursday 20. April 2023
    Thu Apr 20 00:00:00 2023
    The day is 20, the month is April.
    2023
    4
    20
    0
    0
    0
    3
    110
    -1
    2023
    16
    4
    2023-05-20
    

    Python time Module

    An object time class represents the local time of the day. It is independent of any particular day. It the object contains the tzinfo details, it is the aware object. If it is None then the time object is the naive object.

    Syntax

    datetime.time(hour=0, minute=0, second=0, microsecond=0, tzinfo=None)
    

    All arguments are optional. tzinfo may be None, or an instance of a tzinfo subclass. The remaining arguments must be integers in the following ranges −

    • hour − 0 <= hour < 24,
    • minute − 0 <= minute < 60,
    • second − 0 <= second < 60,
    • microsecond − 0 <= microsecond < 1000000

    If any of the arguments are outside those ranges is given, ValueError is raised.

    Example

    from datetime import time
    
    time1 = time(8,14,36)print("Time:", time1)
    
    time2 = time(minute =12)print("time", time2)
    
    time3 = time()print("time", time3)
    
    time4 = time(hour =26)

    It will produce the following output −

    Time: 08:14:36
    time 00:12:00
    time 00:00:00
    Traceback (most recent call last):
      File "/home/cg/root/64b912f27faef/main.py", line 12, in 
    
    time4 = time(hour = 26)
    ValueError: hour must be in 0..23

    Class attributes

    • time.min − The earliest representable time, time(0, 0, 0, 0).
    • time.max − The latest representable time, time(23, 59, 59, 999999).
    • time.resolution − The smallest possible difference between non-equal time objects.

    Example

    from datetime import time
    print(time.min)print(time.max)print(time.resolution)

    It will produce the following output −

    00:00:00
    23:59:59.999999
    0:00:00.000001
    

    Instance attributes

    • time.hour − In range(24)
    • time.minute − In range(60)
    • time.second − In range(60)
    • time.microsecond − In range(1000000)
    • time.tzinfo − the tzinfo argument to the time constructor, or None.

    Example

    from datetime import time
    t = time(8,23,45,5000)print(t.hour)print(t.minute)print(t.second)print(t.microsecond)

    It will produce the following output −

    8
    23
    455000
    

    Instance Methods of time Object

    • replace() − Return a time with the same value, except for those attributes given new values by whichever keyword arguments are specified.
    • isoformat() − Return a string representing the time in ISO 8601 format
    • __str__() − For a time t, str(t) is equivalent to t.isoformat().
    • strftime(format) − Return a string representing the time, controlled by an explicit format string.
    • __format__(format) − Same as time.strftime().
    • utcoffset() − If tzinfo is None, returns None, else returns self.tzinfo.utcoffset(None),
    • dst() − If tzinfo is None, returns None, else returns self.tzinfo.dst(None),
    • tzname() − If tzinfo is None, returns None, else returns self.tzinfo.tzname(None), or raises an exception

    Python datetime object

    An object of datetime class contains the information of date and time together. It assumes the current Gregorian calendar extended in both directions; like a time object, and there are exactly 3600*24 seconds in every day.

    Syntax

    datetime.datetime(year, month, day, hour=0, minute=0, second=0, microsecond=0, tzinfo=None,*, fold=0)

    The year, month and day arguments are required.

    • year − MINYEAR <= year <= MAXYEAR,
    • month − 1 <= month <= 12,
    • day − 1 <= day <= number of days in the given month and year,
    • hour − 0 <= hour < 24,
    • minute − 0 <= minute < 60,
    • second −0 <= second < 60,
    • microsecond − 0 <= microsecond < 1000000,
    • fold − in [0, 1].

    If any argument in outside ranges is given, ValueError is raised.

    Example

    from datetime import datetime
    dt = datetime(2023,4,20)print(dt)
    
    dt = datetime(2023,4,20,11,6,32,5000)print(dt)

    It will produce the following output −

    2023-04-20 00:00:00
    2023-04-20 11:06:32.005000
    

    Class attributes

    • datetime.min − The earliest representable datetime, datetime(MINYEAR, 1, 1, tzinfo=None).
    • datetime.max − The latest representable datetime, datetime(MAXYEAR, 12, 31, 23, 59, 59, 999999, tzinfo=None).
    • datetime.resolution − The smallest possible difference between non-equal datetime objects, timedelta(microseconds=1).

    Example

    from datetime import datetime
    min= datetime.minprint("Min DateTime ",min)max= datetime.maxprint("Max DateTime ",max)

    It will produce the following output −

    Min DateTime 0001-01-01 00:00:00
    Max DateTime 9999-12-31 23:59:59.999999
    

    Instance Attributes of datetime Object

    • datetime.year − Between MINYEAR and MAXYEAR inclusive.
    • datetime.month − Between 1 and 12 inclusive.
    • datetime.day − Between 1 and the number of days in the given month of the given year.
    • datetime.hour − In range(24)
    • datetime.minute − In range(60)
    • datetime.second − In range(60)
    • datetime.microsecond − In range(1000000).
    • datetime.tzinfo − The object passed as the tzinfo argument to the datetime constructor, or None if none was passed.
    • datetime.fold − In [0, 1]. Used to disambiguate wall times during a repeated interval.

    Example

    from datetime import datetime
    dt = datetime.now()print("Day: ", dt.day)print("Month: ", dt.month)print("Year: ", dt.year)print("Hour: ", dt.hour)print("Minute: ", dt.minute)print("Second: ", dt.second)

    It will produce the following output −

    Day: 20
    Month: 4
    Year: 2023
    Hour: 15
    Minute: 5
    Second: 52
    

    Class Methods of datetime Object

    • today() − Return the current local datetime, with tzinfo None.
    • now(tz=None) − Return the current local date and time.
    • utcnow() − Return the current UTC date and time, with tzinfo None.
    • utcfromtimestamp(timestamp) − Return the UTC datetime corresponding to the POSIX timestamp, with tzinfo None
    • fromtimestamp(timestamp, timezone.utc) − On the POSIX compliant platforms, it is equivalent todatetime(1970, 1, 1, tzinfo=timezone.utc) + timedelta(seconds=timestamp)
    • fromordinal(ordinal) − Return the datetime corresponding to the proleptic Gregorian ordinal, where January 1 of year 1 has ordinal 1.
    • fromisoformat(date_string) − Return a datetime corresponding to a date_string in any valid ISO 8601 format.

    Instance Methods of datetime Object

    • date() − Return date object with same year, month and day.
    • time() − Return time object with same hour, minute, second, microsecond and fold.
    • timetz() − Return time object with same hour, minute, second, microsecond, fold, and tzinfo attributes. See also method time().
    • replace() − Return a datetime with the same attributes, except for those attributes given new values by whichever keyword arguments are specified.
    • astimezone(tz=None) − Return a datetime object with new tzinfo attribute tz
    • utcoffset() − If tzinfo is None, returns None, else returns self.tzinfo.utcoffset(self)
    • dst() − If tzinfo is None, returns None, else returns self.tzinfo.dst(self)
    • tzname() − If tzinfo is None, returns None, else returns self.tzinfo.tzname(self)
    • timetuple() − Return a time.struct_time such as returned by time.localtime().
    • atetime.toordinal() − Return the proleptic Gregorian ordinal of the date.
    • timestamp() − Return POSIX timestamp corresponding to the datetime instance.
    • isoweekday() − Return day of the week as an integer, where Monday is 1, Sunday is 7.
    • isocalendar() − Return a named tuple with three components: year, week and weekday.
    • isoformat(sep=’T’, timespec=’auto’) − Return a string representing the date and time in ISO 8601 format
    • __str__() − For a datetime instance d, str(d) is equivalent to d.isoformat(‘ ‘).
    • ctime() − Return a string representing the date and time:
    • strftime(format) − Return a string representing the date and time, controlled by an explicit format string.
    • __format__(format) − Same as strftime().

    Example

    from datetime import datetime, date, time, timezone
    
    # Using datetime.combine()
    d = date(2022,4,20)
    t = time(12,30)
    datetime.combine(d, t)# Using datetime.now()
    d = datetime.now()print(d)# Using datetime.strptime()
    dt = datetime.strptime("23/04/20 16:30","%d/%m/%y %H:%M")# Using datetime.timetuple() to get tuple of all attributes
    tt = dt.timetuple()for it in tt:print(it)# Date in ISO format
    ic = dt.isocalendar()for it in ic:print(it)

    It will produce the following output −

    2023-04-20 15:12:49.816343
    2020
    4
    23
    16
    30
    0
    3
    114
    -1
    2020
    17
    4
    

    Python timedelta Object

    The timedelta object represents the duration between two dates or two time objects.

    Syntax

    datetime.timedelta(days=0, seconds=0, microseconds=0, milliseconds=0, minutes=0, hours=0, weeks=0)

    Internally, the attributes are stored in days, seconds and microseconds. Other arguments are converted to those units −

    • A millisecond is converted to 1000 microseconds.
    • A minute is converted to 60 seconds.
    • An hour is converted to 3600 seconds.
    • A week is converted to 7 days.

    While days, seconds and microseconds are then normalized so that the representation is unique.

    Example

    The following example shows that Python internally stores days, seconds and microseconds only.

    from datetime import timedelta
    delta = timedelta(
       days=100,
       seconds=27,
       microseconds=10,
       milliseconds=29000,
       minutes=5,
       hours=12,
       weeks=2)# Only days, seconds, and microseconds remainprint(delta)

    It will produce the following output −

    114 days, 12:05:56.000010
    

    Example

    The following example shows how to add timedelta object to a datetime object.

    from datetime import datetime, timedelta
    
    date1 = datetime.now()
    
    date2= date1+timedelta(days =4)print("Date after 4 days:", date2)
    
    date3 = date1-timedelta(15)print("Date before 15 days:", date3)

    It will produce the following output −

    Date after 4 days: 2023-04-24 18:05:39.509905
    Date before 15 days: 2023-04-05 18:05:39.509905
    

    Class Attributes of timedelta Object

    • timedelta.min − The most negative timedelta object, timedelta(-999999999).
    • timedelta.max − The most positive timedelta object, timedelta(days=999999999, hours=23, minutes=59, seconds=59, microseconds=999999).
    • timedelta.resolution − The smallest possible difference between non-equal timedelta objects, timedelta(microseconds=1)

    Example

    from datetime import timedelta
    
    # Getting minimum valuemin= timedelta.minprint("Minimum value:",min)max= timedelta.maxprint("Maximum value",max)

    It will produce the following output −

    Minimum value: -999999999 days, 0:00:00
    Maximum value 999999999 days, 23:59:59.999999
    

    Instance Attributes of timedelta Object

    Since only day, second and microseconds are stored internally, those are the only instance attributes for a timedelta object.

    • days − Between -999999999 and 999999999 inclusive
    • seconds − Between 0 and 86399 inclusive
    • microseconds − Between 0 and 999999 inclusive

    Instance Methods of timedelta Object

    timedelta.total_seconds() − Return the total number of seconds contained in the duration.

    Example

    from datetime import timedelta
    year = timedelta(days=365)
    years =5* year
    print(years)print(years.days //365)646
    year_1 = years //5print(year_1.days)

    It will produce the following output −

    1825 days, 0:00:00
    5
    365
  • Generics

    In Python, generics is a mechanism with which you to define functions, classes, or methods that can operate on multiple types while maintaining type safety. With the implementation of Generics enable it is possible to write reusable code that can be used with different data types. It ensures promoting code flexibility and type correctness.

    Normally, in Python programming, you don’t need to declare a variable type. The type is determined dynamically by the value assigned to it. Python’s interpreter doesn’t perform type checks and hence it may raise runtime exceptions.

    Python introduced generics with type hints in version 3.5, allowing you to specify the expected types of variables, function arguments, and return values. This feature helps in reducing runtime errors and improving code readability.

    Generics extend the concept of type hints by introducing type variables, which represent generic types that can be replaced with specific types when using the generic function or class.

    Defining a Generic Function

    Let us have a look at the following example that defines a generic function −

    from typing import List, TypeVar, Generic
    T = TypeVar('T')defreverse(items: List[T])-> List[T]:return items[::-1]

    Here, we define a generic function called ‘reverse’. The function takes a list (‘List[T]’) as an argument and returns a list of the same type. The type variable ‘T’ represents the generic type, which will be replaced with a specific type when the function is used.

    Calling the Generic Function with Different Data Types

    The function reverse() function is called with different data types −

    numbers =[1,2,3,4,5]
    reversed_numbers = reverse(numbers)print(reversed_numbers)
    
    fruits =['apple','banana','cherry']
    reversed_fruits = reverse(fruits)print(reversed_fruits)

    It will produce the following output −

    [5, 4, 3, 2, 1]
    ['cherry', 'banana', 'apple']
    

    Defining a Generic Class

    A generic type is typically declared by adding a list of type parameters after the class name. The following example uses generics with a generic class −

    from typing import List, TypeVar, Generic
    T = TypeVar('T')classBox(Generic[T]):def__init__(self, item: T):
    
      self.item = item
    defget_item(self)-> T:return self.item Let us create objects of the above generic classwithintandstrtype box1 = Box(42)print(box1.get_item()) box2 = Box('Hello')print(box2.get_item())

    It will produce the following output −

    42
    Hello
  • URL Processing

    In the world of Internet, different resources are identified by URLs (Uniform Resource Locators). Python’s standard library includes the urllib package, which has modules for working with URLs. It helps you parse URLs, fetch web content, and manage errors.

    This tutorial introduces urllib basics to help you start using it. Improve your skills in web scraping, fetching data, and managing URLs with Python using urllib.

    The urllib package contains the following modules for processing URLs −

    • urllib.parse module is used for parsing a URL into its parts.
    • urllib.request module contains functions for opening and reading URLs
    • urllib.error module carries definitions of the exceptions raised by urllib.request
    • urllib.robotparser module parses the robots.txt files

    The urllib.parse Module

    This module serves as a standard interface to obtain various parts from a URL string. The module contains following functions −

    urlparse(urlstring)

    Parse a URL into six components, returning a 6-item named tuple. Each tuple item is a string corresponding to following attributes −

    AttributeIndexValue
    scheme0URL scheme specifier
    netloc1Network location part
    path2Hierarchical path
    params3Parameters for last path element
    query4Query component
    fragment5Fragment identifier
    usernameUser name
    passwordPassword
    hostnameHost name (lower case)
    PortPort number as integer, if present

    Example

    from urllib.parse import urlparse
    url ="https://example.com/employees/name/?salary>=25000"
    parsed_url = urlparse(url)print(type(parsed_url))print("Scheme:",parsed_url.scheme)print("netloc:", parsed_url.netloc)print("path:", parsed_url.path)print("params:", parsed_url.params)print("Query string:", parsed_url.query)print("Frgment:", parsed_url.fragment)

    It will produce the following output −

    <class 'urllib.parse.ParseResult'>
    Scheme: https
    netloc: example.com
    path: /employees/name/
    params:
    Query string: salary>=25000
    Frgment:
    

    parse_qs(qs))

    This function Parse a query string given as a string argument. Data is returned as a dictionary. The dictionary keys are the unique query variable names and the values are lists of values for each name.

    To further fetch the query parameters from the query string into a dictionary, use parse_qs() function of the query attribute of ParseResult object as follows −

    Example

    from urllib.parse import urlparse, parse_qs
    url ="https://example.com/employees?name=Anand&salary=25000"
    parsed_url = urlparse(url)
    dct = parse_qs(parsed_url.query)print("Query parameters:", dct)

    It will produce the following output −

    Query parameters: {'name': ['Anand'], 'salary': ['25000']}
    

    urlsplit(urlstring)

    This is similar to urlparse(), but does not split the params from the URL. This should generally be used instead of urlparse() if the more recent URL syntax allowing parameters to be applied to each segment of the path portion of the URL is wanted.

    urlunparse(parts)

    This function is the opposite of urlparse() function. It constructs a URL from a tuple as returned by urlparse(). The parts argument can be any six-item iterable. This returns an equivalent URL.

    Example

    from urllib.parse import urlunparse
    
    lst =['https','example.com','/employees/name/','','salary>=25000','']
    new_url = urlunparse(lst)print("URL:", new_url)

    It will produce the following output −

    URL: https://example.com/employees/name/?salary>=25000
    

    urlunsplit(parts)

    Combine the elements of a tuple as returned by urlsplit() into a complete URL as a string. The parts argument can be any five-item iterable.

    The urllib.request Module

    This module offers the functions and classes for handling the URL’s opening and reading operations by using the urlopen() function.

    urlopen() function

    This function opens the given URL, which can be either a string or a Request object. The optional timeout parameter specifies a timeout in seconds for blocking operations This actually only works for HTTP, HTTPS and FTP connections.

    This function always returns an object which can work as a context manager and has the properties url, headers, and status. For HTTP and HTTPS URLs, this function returns a http.client.HTTPResponse object slightly modified.

    Example

    The following code uses urlopen() function to read the binary data from an image file, and writes it to local file. You can open the image file on your computer using any image viewer.

    from urllib.request import urlopen
    obj = urlopen("https://www.tutorialspoint.com/images/logo.png")
    data = obj.read()
    img =open("img.jpg","wb")
    img.write(data)
    img.close()

    It will produce the following output −

    urllib_request

    The Request Object

    The urllib.request module includes Request class. This class is an abstraction of a URL request. The constructor requires a mandatory string argument a valid URL.

    Syntax

    urllib.request.Request(url, data, headers, origin_req_host, method=None)

    Parameters

    • url − A string that is a valid URL
    • data − An object specifying additional data to send to the server. This parameter can only be used with HTTP requests. Data may be bytes, file-like objects, and iterables of bytes-like objects.
    • headers − Should be a dictionary of headers and their associated values.
    • origin_req_host − Should be the request-host of the origin transaction
    • method − should be a string that indicates the HTTP request method. One of GET, POST, PUT, DELETE and other HTTP verbs. Default is GET.

    Example

    from urllib.request import Request
    obj = Request("https://www.tutorialspoint.com/")

    This Request object can now be used as an argument to urlopen() method.

    from urllib.request import Request, urlopen
    obj = Request("https://www.tutorialspoint.com/")
    resp = urlopen(obj)

    The urlopen() function returns a HttpResponse object. Calling its read() method fetches the resource at the given URL.

    from urllib.request import Request, urlopen
    obj = Request("https://www.tutorialspoint.com/")
    resp = urlopen(obj)
    data = resp.read()print(data)

    Sending Data

    If you define data argument to the Request constructor, a POST request will be sent to the server. The data should be any object represented in bytes.

    from urllib.request import Request, urlopen
    from urllib.parse import urlencode
    
    values ={'name':'Madhu','location':'India','language':'Hindi'}
    data = urlencode(values).encode('utf-8')
    obj = Request("https://example.com", data)

    Sending Headers

    The Request constructor also accepts header argument to push header information into the request. It should be in a dictionary object.

    headers ={'User-Agent': user_agent}
    obj = Request("https://example.com", data, headers)

    The urllib.error Module

    Following exceptions are defined in urllib.error module −

    URLError

    URLError is raised because there is no network connection (no route to the specified server), or the specified server doesn’t exist. In this case, the exception raised will have a ‘reason’ attribute.

    Example

    from urllib.request import Request, urlopen
    import urllib.error as err
    
    obj = Request("http://www.nosuchserver.com")try:
       urlopen(obj)except err.URLError as e:print(e)

    It will produce the following output −

    HTTP Error 403: Forbidden
    

    HTTPError

    Every time the server sends a HTTP response it is associated with a numeric “status code”. It code indicates why the server is unable to fulfill the request. The default handlers will handle some of these responses for you. For those it can’t handle, urlopen() function raises an HTTPError. Typical examples of HTTPErrors are ‘404’ (page not found), ‘403’ (request forbidden), and ‘401’ (authentication required).

    Example

    from urllib.request import Request, urlopen
    import urllib.error as err
    
    obj = Request("http://www.python.org/fish.html")try:
       urlopen(obj)except err.HTTPError as e:print(e.code)

    It will produce the following output −

    404
  • Socket Programming

    Python Socket Programming

    Socket programming is a technique in which we communicate between two nodes connected in a network where the server node listens to the incoming requests from the client nodes.

    In Python, the socket module is used for socket programming. The socketmodule in the standard library included functionality required for communication between server and client at hardware level.

    This module provides access to the BSD socket interface. It is available on all operating systems such as Linux, Windows, MacOS.

    What are Sockets?

    Sockets are the endpoints of a bidirectional communications channel. Sockets may communicate within a process, between processes on the same machine, or between processes on different continents.

    A socket is identified by the combination of IP address and the port number. It should be properly configured at both ends to begin communication.

    connection
    IP_address

    Sockets may be implemented over a number of different channel types: Unix domain sockets, TCP, UDP, and so on. The socket library provides specific classes for handling the common transports as well as a generic interface for handling the rest.

    The term socket programming implies programmatically setting up sockets to be able to send and receive data.

    There are two types of communication protocols −

    • connection-oriented protocol
    • connection-less protocol

    TCP or Transmission Control Protocol is a connection-oriented protocol. The data is transmitted in packets by the server, and assembled in the same order of transmission by the receiver. Since the sockets at either end of the communication need to be set before starting, this method is more reliable.

    UDP or User Datagram Protocol is connectionless. The method is not reliable because the sockets does not require establishing any connection and termination process for transferring the data.

    Python socket Module

    The socket module is used for creating and managing socket programming for the connected nodes in a network. The socket module provides a socket class. You need to create a socket using the socket.socket() constructor.

    An object of the socket class represents the pair of host name and the port numbers.

    Syntax

    The following is the syntax of socket.socket() constructor –

    socket.socket (socket_family, socket_type, protocol=0)

    Parameters

    • family − AF_INET by default. Other values – AF_INET6 (eight groups of four hexadecimal digits), AF_UNIX, AF_CAN (Controller Area Network) or AF_RDS (Reliable Datagram Sockets).
    • socket_type − should be SOCK_STREAM (the default), SOCK_DGRAM, SOCK_RAW or perhaps one of the other SOCK_ constants.
    • protocol − number is usually zero and may be omitted.

    Return Type

    This method returns a socket object.

    Once you have the socket object, then you can use the required methods to create your client or server program.

    Server Socket Methods

    The socket instantiated on server is called server socket. Following methods are available to the socket object on the server −

    • bind() method − This method binds the socket to specified IP address and port number.
    • listen() method − This method starts server and runs into a listen loop looking for connection request from client.
    • accept() method − When connection request is intercepted by server, this method accepts it and identifies the client socket with its address.

    To create a socket on a server, use the following snippet −

    import socket
    server = socket.socket()
    server.bind(('localhost',12345))
    server.listen()
    client, addr = server.accept()print("connection request from: "+str(addr))

    By default, the server is bound to local machine’s IP address ‘localhost’ listening at arbitrary empty port number.

    Client Socket Methods

    Similar socket is set up on the client end. It mainly sends connection request to server socket listening at its IP address and port number

    connect() method

    This method takes a two-item tuple object as argument. The two items are IP address and port number of the server.

    obj=socket.socket()
    obj.connect((host,port))

    Once the connection is accepted by the server, both the socket objects can send and/or receive data.

    send() method

    The server sends data to client by using the address it has intercepted.

    client.send(bytes)

    Client socket sends data to socket it has established connection with.

    sendall() method

    similar to send(). However, unlike send(),this method continues to send data from bytes until either all data has been sent or an error occurs. None is returned on success.

    sendto() method

    This method is to be used in case of UDP protocol only.

    recv() method

    This method is used to retrieve data sent to the client. In case of server, it uses the remote socket whose request has been accepted.

    client.recv(bytes)

    recvfrom() method

    This method is used in case of UDP protocol.

    Python – Socket Server

    To write Internet servers, we use the socket function available in socket module to create a socket object. A socket object is then used to call other functions to setup a socket server.

    Now call the bind(hostname, port) function to specify a port for your service on the given host.

    Next, call the accept method of the returned object. This method waits until a client connects to the port you specified, and then returns a connection object that represents the connection to that client.

    Example of Server Socket

    import socket
    host ="127.0.0.1"
    port =5001
    server = socket.socket()
    server.bind((host,port))
    server.listen()
    conn, addr = server.accept()print("Connection from: "+str(addr))whileTrue:
       data = conn.recv(1024).decode()ifnot data:break
       data =str(data).upper()print(" from client: "+str(data))
       data =input("type message: ")
       conn.send(data.encode())
    conn.close()

    Python – Socket Client

    Let us write a very simple client program, which opens a connection to a given port 5001 and a given localhost. It is very simple to create a socket client using the Python’s socket module function.

    The socket.connect(hosname, port) opens a TCP connection to hostname on the port. Once you have a socket open, you can read from it like any IO object. When done, remember to close it, as you would close a file.

    Example of Client Socket

    The following code is a very simple client that connects to a given host and port, reads any available data from the socket, and then exits when ‘q’ is entered.

    import socket
    host ='127.0.0.1'
    port =5001
    obj = socket.socket()
    obj.connect((host,port))
    message =input("type message: ")while message !='q':
       obj.send(message.encode())
       data = obj.recv(1024).decode()print('Received from server: '+ data)
       message =input("type message: ")
    obj.close()
    • Run Server code first. It starts listening.
    • Then start client code. It sends request.
    • Request accepted. Client address identified
    • Type some text and press Enter.
    • Data received is printed. Send data to client.
    • Data from server is received.
    • Loop terminates when ‘q’ is input.

    Server-client interaction is shown below −

    server_client_interaction

    We have implemented client-server communication with socket module on the local machine. To put server and client codes on two different machines on a network, we need to find the IP address of the server machine.

    On Windows, you can find the IP address by running ipconfig command. The ifconfig command is the equivalent command on Ubuntu.

    ipv4_address

    Change host string in both the server and client codes with IPv4 Address value and run them as before.

    Python File Transfer with Socket Module

    The following program demonstrates how socket communication can be used to transfer a file from server to the client

    Server Code

    The code for establishing connection is same as before. After the connection request is accepted, a file on server is opened in binary mode for reading, and bytes are successively read and sent to the client stream till end of file is reached.

    import socket
    host ="127.0.0.1"
    port =5001
    server = socket.socket()
    server.bind((host, port))
    server.listen()
    conn, addr = server.accept()
    data = conn.recv(1024).decode()
    filename='test.txt'
    f =open(filename,'rb')whileTrue:
       l = f.read(1024)ifnot l:break
       conn.send(l)print('Sent ',repr(l))
    f.close()print('File transferred')
    conn.close()

    Client Code

    On the client side, a new file is opened in wb mode. The stream of data received from server is written to the file. As the stream ends, the output file is closed. A new file will be created on the client machine.

    import socket
    
    s = socket.socket()
    host ="127.0.0.1"
    port =5001
    
    s.connect((host, port))
    s.send("Hello server!".encode())withopen('recv.txt','wb')as f:whileTrue:print('receiving data...')
    
      data = s.recv(1024)ifnot data:break
      f.write(data)
      
    f.close()print('Successfully received') s.close()print('connection closed')

    The Python socketserver Module

    The socketserver module in Python’s standard library is a framework for simplifying task of writing network servers. There are following classes in module, which represent synchronous servers −

    socketserver_module

    These classes work with corresponding RequestHandler classes for implementing the service. BaseServer is the superclass of all Server objects in the module.

    TCPServer class uses the internet TCP protocol, to provide continuous streams of data between the client and server. The constructor automatically attempts to invoke server_bind() and server_activate(). The other parameters are passed to the BaseServer base class.

    You must also create a subclass of StreamRequestHandler class. IT provides self.rfile and self.wfile attributes to read or write to get the request data or return data to the client.

    • UDPServer and DatagramRequestHandler − These classes are meant to be used for UDP protocol.
    • DatagramRequestHandler and UnixDatagramServer − These classes use Unix domain sockets; they’re not available on non-Unix platforms.

    Server Code

    You must write a RequestHandler class. It is instantiated once per connection to the server, and must override the handle() method to implement communication to the client.

    import socketserver
    classMyTCPHandler(socketserver.BaseRequestHandler):defhandle(self):
    
      self.data = self.request.recv(1024).strip()
      host,port=self.client_address
      print("{}:{} wrote:".format(host,port))print(self.data.decode())
      msg=input("enter text .. ")
      self.request.sendall(msg.encode())</pre>

    On the server's assigned port number, an object of TCPServer class calls the forever() method to put the server in the listening mode and accepts incoming requests from clients.

    if __name__ =="__main__":
       HOST, PORT ="localhost",9999with socketserver.TCPServer((HOST, PORT), MyTCPHandler)as server:
    
      server.serve_forever()</pre>

    Client Code

    When working with socketserver, the client code is more or less similar with the socket client application.

    import socket
    import sys
    
    HOST, PORT ="localhost",9999whileTrue:with socket.socket(socket.AF_INET, socket.SOCK_STREAM)as sock:# Connect to server and send data
    
      sock.connect((HOST, PORT))
      data =input("enter text .. .")
      sock.sendall(bytes(data +"\n","utf-8"))# Receive data from the server and shut down
      received =str(sock.recv(1024),"utf-8")print("Sent: {}".format(data))print("Received: {}".format(received))</pre>

    Run the server code in one command prompt terminal. Open multiple terminals for client instances. You can simulate a concurrent communication between the server and more than one clients.

    ServerClient-1Client-2
    D:\socketsrvr>python myserver.py127.0.0.1:54518 wrote:from client-1enter text ..hello127.0.0.1:54522 wrote:how are youenter text ..fine127.0.0.1:54523 wrote:from client-2enter text ..hi client-2127.0.0.1:54526 wrote:good byeenter text ..bye bye127.0.0.1:54530 wrote:thanksenter text ..bye client-2
  • Network Programming

    The threading module in Python’s standard library is capable of handling multiple threads and their interaction within a single process. Communication between two processes running on the same machine is handled by Unix domain sockets, whereas for the processes running on different machines connected with TCP (Transmission control protocol), Internet domain sockets are used.

    network_programming

    Python’s standard library consists of various built-in modules that support interprocess communication and networking. Python provides two levels of access to the network services. At a low level, you can access the basic socket support in the underlying operating system, which allows you to implement clients and servers for both connection-oriented and connectionless protocols.

    Python also has libraries that provide higher-level access to specific application-level network protocols, such as FTP, HTTP, and so on.

    ProtocolCommon functionPort NoPython module
    HTTPWeb pages80httplib, urllib, xmlrpclib
    NNTPUsenet news119nntplib
    FTPFile transfers20ftplib, urllib
    SMTPSending email25smtplib
    POP3Fetching email110poplib
    IMAP4Fetching email143imaplib
    TelnetCommand lines23telnetlib
    GopherDocument transfers70gopherlib, urllib
  •  Interrupting a Thread

    Interrupting a thread in Python is a common requirement in multi-threaded programming, where a thread’s execution needs to be terminated under certain conditions. In a multi-threaded program, a task in a new thread, may be required to be stopped. This may be for many reasons, such as − task completion, application shutdown, or other external conditions.

    In Python, interrupting threads can be achieved using threading.Event or by setting a termination flag within the thread itself. These methods allow you to interrupt the threads effectively, ensuring that resources are properly released and threads exit cleanly.

    Thread Interruption using Event Object

    One of the straightforward ways to interrupt a thread is by using the threading.Event class. This class allows one thread to signal to another that a particular event has occurred. Here’s how you can implement thread interruption using threading.Event

    Example

    In this example, we have a MyThread class. Its object starts executing the run() method. The main thread sleeps for a certain period and then sets an event. Till the event is detected, loop in the run() method continues. As soon as the event is detected, the loop terminates.

    from time import sleep
    from threading import Thread
    from threading import Event
    
    classMyThread(Thread):def__init__(self, event):super(MyThread, self).__init__()
    
      self.event = event
    defrun(self):
      i=0whileTrue:
         i+=1print('Child thread running...',i)
         sleep(0.5)if self.event.is_set():breakprint()print('Child Thread Interrupted')
    event = Event() thread1 = MyThread(event) thread1.start() sleep(3)print('Main thread stopping child thread') event.set() thread1.join()

    When you execute this code, it will produce the following output −

    Child thread running... 1
    Child thread running... 2
    Child thread running... 3
    Child thread running... 4
    Child thread running... 5
    Child thread running... 6
    Main thread stopping child thread
    Child Thread Interrupted

    Thread Interruption using a Flag

    Another approach to interrupting threads is by using a flag that the thread checks at regular intervals. This method involves setting a flag attribute in the thread object and regularly checking its value in the thread's execution loop.

    Example

    This example demonstrates how to use a flag to control and stop a running thread in Python multithreaded program.

    import threading
    import time

    def foo():
    t = threading.current_thread()
    while getattr(t, "do_run", True):
    print("working on a task")
    time.sleep(1)
    print("Stopping the Thread after some time.")

    # Create a thread
    t = threading.Thread(target=foo)
    t.start()

    # Allow the thread to run for 5 seconds
    time.sleep(5)

    # Set the termination flag to stop the thread
    t.do_run = False
    When you execute this code, it will produce the following output −

    working on a task
    working on a task
    working on a task
    working on a task
    working on a task
    Stopping the Thread after some time.
  • Thread Deadlock

    A deadlock may be described as a concurrency failure mode. It is a situation in a program where one or more threads wait for a condition that never occurs. As a result, the threads are unable to progress and the program is stuck or frozen and must be terminated manually.

    Deadlock situation may arise in many ways in your concurrent program. Deadlocks are never not developed intentionally, instead, they are in fact a side effect or bug in the code.

    Common causes of thread deadlocks are listed below −

    • A thread that attempts to acquire the same mutex lock twice.
    • Threads that wait on each other (e.g. A waits on B, B waits on A).
    • When a thread that fails to release a resource such as lock, semaphore, condition, event, etc.
    • Threads that acquire mutex locks in different orders (e.g. fail to perform lock ordering).

    How to Avoid Deadlocks in Python Threads

    When multiple threads in a multi-threaded application attempt to access the same resource, such as performing read/write operations on the same file, it can lead to data inconsistency. Therefore, it is important to synchronize concurrent access to resources by using locking mechanisms.

    The Python threading module provides a simple-to-implement locking mechanism to synchronize threads. You can create a new lock object by calling the Lock() class, which initializes the lock in an unlocked state.

    Locking Mechanism with the Lock Object

    An object of the Lock class has two possible states − locked or unlocked, initially in unlocked state when first created. A lock doesn’t belong to any particular thread.

    The Lock class defines acquire() and release() methods.

    The acquire() Method

    The acquire() method of the Lock class changes the lock’s state from unlocked to locked. It returns immediately unless the optional blocking argument is set to True, in which case it waits until the lock is acquired.

    Here is the Syntax of this method −

    Lock.acquire(blocking, timeout)

    Where, 

    • blocking − If set to False, it means do not block. If a call with blocking set to True would block, return False immediately; otherwise, set the lock to locked and return True.
    • timeout − Specifies a timeout period for acquiring the lock.

    The return value of this method is True if the lock is acquired successfully; False if not.

    The release() Method

    When the state is locked, this method in another thread changes it to unlocked. This can be called from any thread, not only the thread which has acquired the lock

    Following is the Syntax of the release() method −

    Lock.release()

    The release() method should only be called in the locked state. If an attempt is made to release an unlocked lock, a RuntimeError will be raised.

    When the lock is locked, reset it to unlocked, and return. If any other threads are blocked waiting for the lock to become unlocked, allow exactly one of them to proceed. There is no return value of this method.

    Example

    In the following program, two threads try to call the synchronized() method. One of them acquires the lock and gains the access while the other waits. When the run() method is completed for the first thread, the lock is released and the synchronized method is available for second thread.

    When both the threads join, the program comes to an end.

    from threading import Thread, Lock
    import time
    
    lock=Lock()
    threads=[]classmyThread(Thread):def__init__(self,name):
    
      Thread.__init__(self)
      self.name=name
    defrun(self):
      lock.acquire()
      synchronized(self.name)
      lock.release()defsynchronized(threadName):print("{} has acquired lock and is running synchronized method".format(threadName))
    counter=5while counter:print('**', end='')
      time.sleep(2)
      counter=counter-1print('\nlock released for', threadName)
    t1=myThread('Thread1') t2=myThread('Thread2') t1.start() threads.append(t1) t2.start() threads.append(t2)for t in threads: t.join()print("end of main thread")

    It will produce the following output −

    Thread1 has acquired lock and is running synchronized method
    **********
    lock released for Thread1
    Thread2 has acquired lock and is running synchronized method
    **********
    lock released for Thread2
    end of main thread
    

    Semaphore Object for Synchronization

    In addition to locks, Python threading module supports semaphores, which offering another synchronization technique. It is one of the oldest synchronization techniques invented by a well-known computer scientist, Edsger W. Dijkstra.

    The basic concept of semaphore is to use an internal counter which is decremented by each acquire() call and incremented by each release() call. The counter can never go below zero; when acquire() finds that it is zero, it blocks, waiting until some other thread calls release().

    The Semaphore class in threading module defines acquire() and release() methods.

    The acquire() Method

    If the internal counter is larger than zero on entry, decrement it by one and return True immediately.

    If the internal counter is zero on entry, block until awoken by a call to release(). Once awoken (and the counter is greater than 0), decrement the counter by 1 and return True. Exactly one thread will be awoken by each call to release(). The order in which threads awake is arbitrary.

    If blocking parameter is 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.

    The release() Method

    Release a semaphore, incrementing the internal counter by 1. When it was zero on entry and other threads are waiting for it to become larger than zero again, wake up n of those threads.

    Example

    This example demonstrates how to use a Semaphore object in Python to control access to a shared resource among multiple threads, for avoiding deadlock in Python’s multi-threaded program.

    from threading import*import time
    
    # creating thread instance where count = 3
    lock = Semaphore(4)# creating instancedefsynchronized(name):# calling acquire method
       lock.acquire()for n inrange(3):print('Hello! ', end ='')
    
      time.sleep(1)print( name)# calling release method
      lock.release()# creating multiple thread
    thread_1 = Thread(target = synchronized , args =('Thread 1',)) thread_2 = Thread(target = synchronized , args =('Thread 2',)) thread_3 = Thread(target = synchronized , args =('Thread 3',))# calling the threads thread_1.start() thread_2.start() thread_3.start()

    It will produce the following output −

    Hello! Hello! Hello! Thread 1 Hello! Thread 2 Thread 3 Hello! Hello! Thread 1 Hello! Thread 3 Thread 2 Hello! Hello! Thread 1 Thread 3 Thread 2

  • InterThread Communication

    Inter-Thread Communication refers to the process of enabling communication and synchronization between threads within a Python multi-threaded program.

    Generally, threads in Python share the same memory space within a process, which allows them to exchange data and coordinate their activities through shared variables, objects, and specialized synchronization mechanisms provided by the threading module.

    To facilitate inter-thread communication, the threading module provides various synchronization primitives like, Locks, Events, Conditions, and Semaphores objects. In this tutorial you will learn how to use the Event and Condition object for providing the communication between threads in a multi-threaded program.

    The Event Object

    An Event object manages the state of an internal flag so that threads can wait or set. Event object provides methods to control the state of this flag, allowing threads to synchronize their activities based on shared conditions.

    The flag is initially false and becomes true with the set() method and reset to false with the clear() method. The wait() method blocks until the flag is true.

    Following are the key methods of the Event object −

    • is_set(): Return True if and only if the internal flag is true.
    • set(): Set the internal flag to true. All threads waiting for it to become true are awakened. Threads that call wait() once the flag is true will not block at all.
    • clear(): Reset the internal flag to false. Subsequently, threads calling wait() will block until set() is called to set the internal flag to true again.
    • wait(timeout=None): Block until the internal flag is true. If the internal flag is true on entry, return immediately. Otherwise, block until another thread calls set() to set the flag to true, or until the optional timeout occurs. When the timeout argument is present and not None, it should be a floating point number specifying a timeout for the operation in seconds.

    Example

    The following code attempts to simulate the traffic flow being controlled by the state of traffic signal either GREEN or RED.

    There are two threads in the program, targeting two different functions. The signal_state() function periodically sets and resets the event indicating change of signal from GREEN to RED.

    The traffic_flow() function waits for the event to be set, and runs a loop till it remains set.

    from threading import Event, Thread
    import time
    
    terminate =Falsedefsignal_state():global terminate
    
    whilenot terminate:
        time.sleep(0.5)print("Traffic Police Giving GREEN Signal")
        event.set()
        time.sleep(1)print("Traffic Police Giving RED Signal")
        event.clear()deftraffic_flow():global terminate
    num =0while num &lt;10andnot terminate:print("Waiting for GREEN Signal")
        event.wait()print("GREEN Signal ... Traffic can move")while event.is_set()andnot terminate:
            num +=1print("Vehicle No:", num," Crossing the Signal")
            time.sleep(1)print("RED Signal ... Traffic has to wait")
    event = Event() t1 = Thread(target=signal_state) t2 = Thread(target=traffic_flow) t1.start() t2.start()# Terminate the threads after some time time.sleep(5) terminate =True# join all threads to complete t1.join() t2.join()print("Exiting Main Thread")

    Output

    On executing the above code you will get the following output −

    Waiting for GREEN Signal
    Traffic Police Giving GREEN Signal
    GREEN Signal ... Traffic can move
    Vehicle No: 1 Crossing the Signal
    Traffic Police Giving RED Signal
    RED Signal ... Traffic has to wait
    Waiting for GREEN Signal
    Traffic Police Giving GREEN Signal
    GREEN Signal ... Traffic can move
    Vehicle No: 2 Crossing the Signal
    Vehicle No: 3 Crossing the Signal
    Traffic Police Giving RED Signal
    Traffic Police Giving GREEN Signal
    Vehicle No: 4 Crossing the Signal
    Traffic Police Giving RED Signal
    RED Signal ... Traffic has to wait
    Traffic Police Giving GREEN Signal
    Traffic Police Giving RED Signal
    Exiting Main Thread
    The Condition Object

    The Condition object in Python's threading module provides a more advanced synchronization mechanism. It allows threads to wait for a notification from another thread before proceeding. The Condition object are always associated with a lock and provide mechanisms for signaling between threads.

    Following is the syntax of the threading.Condition() class −

    threading.Condition(lock=None)
    Below are the key methods of the Condition object −

    acquire(*args): Acquire the underlying lock. This method calls the corresponding method on the underlying lock; the return value is whatever that method returns.
    release(): Release the underlying lock. This method calls the corresponding method on the underlying lock; there is no return value.
    wait(timeout=None): This method releases the underlying lock, and then blocks until it is awakened by a notify() or notify_all() call for the same condition variable in another thread, or until the optional timeout occurs. Once awakened or timed out, it re-acquires the lock and returns.
    wait_for(predicate, timeout=None): This utility method may call wait() repeatedly until the predicate is satisfied, or until a timeout occurs. The return value is the last return value of the predicate and will evaluate to False if the method timed out.
    notify(n=1): This method wakes up at most n of the threads waiting for the condition variable; it is a no-op if no threads are waiting.
    notify_all(): Wake up all threads waiting on this condition. This method acts like notify(), but wakes up all waiting threads instead of one. If the calling thread has not acquired the lock when this method is called, a RuntimeError is raised.
    Example

    This example demonstrates a simple form of inter-thread communication using the Condition object of the Python's threading module. Here thread_a and thread_b are communicated using a Condition object, the thread_a waits until it receives a notification from thread_b. the thread_b sleeps for 2 seconds before notifying thread_a and then finishes.

    from threading import Condition, Thread
    import time

    c = Condition()

    def thread_a():
    print("Thread A started")
    with c:
    print("Thread A waiting for permission...")
    c.wait()
    print("Thread A got permission!")
    print("Thread A finished")

    def thread_b():
    print("Thread B started")
    with c:
    time.sleep(2)
    print("Notifying Thread A...")
    c.notify()
    print("Thread B finished")

    Thread(target=thread_a).start()
    Thread(target=thread_b).start()
    Output

    On executing the above code you will get the following output −

    Thread A started
    Thread A waiting for permission...
    Thread B started
    Notifying Thread A...
    Thread B finished
    Thread A got permission!
    Thread A finished
    Example

    Here is another code demonstrating how the Condition object is used for providing the communication between threads. In this, the thread t2 runs the taskB() function, and the thread t1 runs the taskA() function. The t1 thread acquires the condition and notifies it.

    By that time, the t2 thread is in a waiting state. After the condition is released, the waiting thread proceeds to consume the random number generated by the notifying function.

    from threading import Condition, Thread
    import time
    import random

    numbers = []

    def taskA(c):
    for _ in range(5):
    with c:
    num = random.randint(1, 10)
    print("Generated random number:", num)
    numbers.append(num)
    print("Notification issued")
    c.notify()
    time.sleep(0.3)

    def taskB(c):
    for i in range(5):
    with c:
    print("waiting for update")
    while not numbers:
    c.wait()
    print("Obtained random number", numbers.pop())
    time.sleep(0.3)

    c = Condition()
    t1 = Thread(target=taskB, args=(c,))
    t2 = Thread(target=taskA, args=(c,))
    t1.start()
    t2.start()
    t1.join()
    t2.join()
    print("Done")
    When you execute this code, it will produce the following output −

    waiting for update
    Generated random number: 2
    Notification issued
    Obtained random number 2
    Generated random number: 5
    Notification issued
    waiting for update
    Obtained random number 5
    Generated random number: 1
    Notification issued
    waiting for update
    Obtained random number 1
    Generated random number: 9
    Notification issued
    waiting for update
    Obtained random number 9
    Generated random number: 2
    Notification issued
    waiting for update
    Obtained random number 2
    Done
  •  Synchronizing Threads

    In Python, when multiple threads are working concurrently with shared resources, it’s important to synchronize their access to maintain data integrity and program correctness. Synchronizing threads in python can be achieved using various synchronization primitives provided by the threading module, such as locks, conditions, semaphores, and barriers to control access to shared resources and coordinate the execution of multiple threads.

    In this tutorial, we’ll learn about various synchronization primitives provided by Python’s threading module.

    Thread Synchronization using Locks

    The lock object in the Python’s threading module provide the simplest synchronization primitive. They allow threads to acquire and release locks around critical sections of code, ensuring that only one thread can execute the protected code at a time.

    A new lock is created by calling the Lock() method, which returns a lock object. The lock can be acquired using the acquire(blocking) method, which force the threads to run synchronously. The optional blocking parameter enables you to control whether the thread waits to acquire the lock and released using the release() method.

    Example

    The following example demonstrates how to use locks (the threading.Lock() method) to synchronize threads in Python, ensuring that multiple threads access shared resources safely and correctly.

    import threading
    
    counter =10defincrement(theLock, N):global counter
       for i inrange(N):
    
      theLock.acquire()
      counter +=1
      theLock.release()
    lock = threading.Lock() t1 = threading.Thread(target=increment, args=[lock,2]) t2 = threading.Thread(target=increment, args=[lock,10]) t3 = threading.Thread(target=increment, args=[lock,4]) t1.start() t2.start() t3.start()# Wait for all threads to completefor thread in(t1, t2, t3): thread.join()print("All threads have completed")print("The Final Counter Value:", counter)

    Output

    When the above code is executed, it produces the following output −

    All threads have completed
    The Final Counter Value: 26
    Condition Objects for Synchronizing Python Threads

    Condition variables enable threads to wait until notified by another thread. They are useful for providing communication between the threads. The wait() method is used to block a thread until it is notified by another thread through notify() or notify_all().

    Example

    This example demonstrates how Condition objects can synchronize threads using the notify() and wait() methods.

    import threading

    counter = 0

    # Consumer function
    def consumer(cv):
    global counter
    with cv:
    print("Consumer is waiting")
    cv.wait() # Wait until notified by increment
    print("Consumer has been notified. Current Counter value:", counter)

    # increment function
    def increment(cv, N):
    global counter
    with cv:
    print("increment is producing items")
    for i in range(1, N + 1):
    counter += i # Increment counter by i

    # Notify the consumer
    cv.notify()
    print("Increment has finished")

    # Create a Condition object
    cv = threading.Condition()

    # Create and start threads
    consumer_thread = threading.Thread(target=consumer, args=[cv])
    increment_thread = threading.Thread(target=increment, args=[cv, 5])

    consumer_thread.start()
    increment_thread.start()

    consumer_thread.join()
    increment_thread.join()

    print("The Final Counter Value:", counter)
    Output

    On executing the above program, it will produce the following output −

    Consumer is waiting
    increment is producing items
    Increment has finished
    Consumer has been notified. Current Counter value: 15
    The Final Counter Value: 15
    Synchronizing threads using the join() Method

    The join() method in Python's threading module is used to wait until all threads have completed their execution. This is a straightforward way to synchronize the main thread with the completion of other threads.

    Example

    This demonstrates synchronization of threads using the join() method to ensure that the main thread waits for all started threads to complete their work before proceeding.

    import threading
    import time

    class MyThread(threading.Thread):
    def __init__(self, threadID, name, counter):
    threading.Thread.__init__(self)
    self.threadID = threadID
    self.name = name
    self.counter = counter

    def run(self):
    print("Starting " + self.name)
    print_time(self.name, self.counter, 3)

    def print_time(threadName, delay, counter):
    while counter:
    time.sleep(delay)
    print("%s: %s" % (threadName, time.ctime(time.time())))
    counter -= 1

    threads = []

    # Create new threads
    thread1 = MyThread(1, "Thread-1", 1)
    thread2 = MyThread(2, "Thread-2", 2)

    # Start the new Threads
    thread1.start()
    thread2.start()

    # Join the threads
    thread1.join()
    thread2.join()

    print("Exiting Main Thread")
    Output

    On executing the above program, it will produce the following output −

    Starting Thread-1
    Starting Thread-2
    Thread-1: Mon Jul 1 16:05:14 2024
    Thread-2: Mon Jul 1 16:05:15 2024
    Thread-1: Mon Jul 1 16:05:15 2024
    Thread-1: Mon Jul 1 16:05:16 2024
    Thread-2: Mon Jul 1 16:05:17 2024
    Thread-2: Mon Jul 1 16:05:19 2024
    Exiting Main Thread
    Additional Synchronization Primitives

    In addition to the above synchronization primitives, Python's threading module offers: −

    RLocks (Reentrant Locks): A variant of locks that allow a thread to acquire the same lock multiple times before releasing it, useful in recursive functions or nested function calls.
    Semaphores:Similar to locks but with a counter. Threads can acquire the semaphore up to a certain limit defined during initialization. Semaphores are useful for limiting access to resources with a fixed capacity.
    Barriers: Allows a fixed number of threads to synchronize at a barrier point and continue executing only when all threads have reached that point. Barriers are useful for coordinating a group of threads that must all complete a certain phase of execution before any of them can proceed further.