8. Introduction to Python#

  • Python in Linux

  • Python virtual environment

  • Conda environment

  • Python programming environment: Jupyter notebook

  • Variabls

  • Data types

  • Operators

  • Data collections: lists, tuples, dictionaries

  • Loops

  • Conditionals

  • Functions

  • Executable python scripts

  • Object classes

  • I/O to Files


8.1. Python in Linux#

  • Python comes with Linux distro, however, the version maybe too old.

which python3

/usr/bin/python3

  • Python modules can be installed with apt, for example

sudo apt install -s python3-numpy

This would require sudo privilege for package installation. However in many cases, users should be able to install python modules themselves.

  • Alternatively, modules can be installed with pip command in the user’s python virtual environment directory.

  • An alternative python installation can be done in the user’s home directory with conda.


8.2. Python virtual environment and pip (Exercise)#

On the desktop, install a package for python virtual environment support:

sudo apt install python3.11-venv

Create virtual environment venv_1 in the home directory with the command below:

python3 -m venv venv_1

You can notice a new directory appeared in the home directory:

ls -l  venv_1

Activate the virtual environment with the command below:

source venv_1/bin/activate

Notice how the command prompt is prefixed with venv_1 now. See what command python3 you are currently using:

which python3

It should point at

    /home/hostadm/venv_1/bin/python3

Upgrade module pip:

python3 -m pip install --upgrade pip

See the python packages currently installed in venv_1:

python3 -m pip list

Install package numpy:

python3 -m pip install numpy

Install package jupyter:

python3 -m pip install jupyter

Check the updated list of installed python packages:

python3 -m pip list

Uninstall jupyter:

python3 -m pip uninstall jupyter

Uninstall another package, webcolors:

python3 -m pip uninstall webcolors

Deactivate the virtual environment:

deactivate

See what command python3 you are currently using:

which python3

It should point at

   /usr/bin/python3

Remove the directory with the virtual environment:

rm -rf venv_1

8.3. Conda environment (Exercise)#

mkdir -p ~/miniconda3
wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh -O ~/miniconda3/miniconda.sh
bash ~/miniconda3/miniconda.sh -b -u -p ~/miniconda3
rm -rf ~/miniconda3/miniconda.sh

After installing, initialize your newly-installed Miniconda:

~/miniconda3/bin/conda init bash

Activate the Conda environment:

source .bashrc

See what Python is used now:

which python3

It should be in th Conda environment now.

To deactivate the Conda environment, run:

conda deactivate

To activate it again:

conda activate

Search Python modules:

conda search jupyter

8.4. Multiple Conda environments (Exercise)#

You may happen to need to install and test a module in the different Conda installation not to break your production system.

Creating a new conda environment, test_env:

conda create -n test_env

List the available conda environents:

conda info --envs

List installed modules in the two environments:

conda list -n base
conda list -n test_env

Switch from base to test_env:

conda deactivate
conda activate test_env

Install package numpy in test_env

conda install numpy

The environment can be saved in a file. The file can be moved to a different system and restored.

conda env export > test_env.yml

Deactivate conda and remove the environment:

conda deactivate
conda remove -n test_env --all

To restore the environment:

conda env create -f test_env.yml

Delete the environment and the backup file:

conda remove -n test_env --all
rm test_env.yml

8.5. Python programming environment: Jupyter notebook (Exercise)#

Install Jupyter notebook on your desktop as user hostadm:

conda install jupyter

Assign the password to jupyter notebook by running command:

jupyter notebook password

Create directory for python projects, and step into the directory:

mkdir Python
cd Python

8.6. Run Jupyter notebook in server mode (Exercise)#

Check if jupyter is already running:

ps -ef | grep jupyter

If it shows up running without using port 8888, terminate it:

killall -9 jupyter-notebook

Start jupyter notebook in the server mode with listening on port tcp/8888:

cd Python
jupyter-notebook --no-browser --port=8888 --ip=* &

Find out the IP address and the port number on the Ravada server for your jupyter notebook by login to the vdi portal and starting the desktop.

Navigate the browser on your laptop or desktop to the IP address and port, for example

http://172.16.26.112:60000

Login with the password you assigned to the jupyter notebook in the previous exercises.

Start a new python3 project in the jupyter notebook.

This is a Jupyter Notebook.

This computational tool allows for Python programming in a web browser without having to use a multi-window environment. You can write and run your code all in one sitting.


print('Hello, World')

#Press `<shift>-<Enter>` keysto execute the script in the jupyter cell.
Hello, World

8.7. Variables#

Coding SYNTAX in critical. 4, 4.0, and ‘4’ all mean the something different.

VARIABLES are used to stored information, such as numbers, integers, strings, lists, arrays, and databases. Be careful not to overuse the same variable- you can overwrite stored data.

Use three variables on the list of 4’s mentioned above.

A variable type is determined usually at the value assignment. Press <shift>-<Enter> keys to execute the script in the jupyter cell.

a = 4
b = 4.0
c = "4"
print(c)
4

8.8. Python built-in data types#

In programming, data type is a critical concept.

Variables can store data of different types, and different types can do different things.

Python has the following data types built-in by default, in these categories:

  • Text Type: str

  • Numeric Types: int, float, complex

  • Sequence Types: list, tuple, range

  • Mapping Type: dict

  • Set Types: set, frozenset

  • Boolean Type: bool

  • Binary Types: bytes, bytearray

Revisit the multiple 4’s used earlier to see those data types.

Press <shift>-<Enter> keys to execute the script in the jupyter cell.

print(a)
type(a)
4
int
print(c)
type(c)
4
str
print(b)
type(b)
4.0
float

There are three numeric types in Python:

  • int

  • float

  • complex

Variables of numeric types are created when you assign a value to them. You can convert from one type to another with the int(), float(), and complex() methods:

Press <shift>-<Enter> keys to execute the script in the jupyter cell.

d = 4.50
type(d)
float
d = int(d)
print(d)
type(d)
4
int

8.9. Python Operators#

Operators are used to perform operations on variables and values. But pay attention: values used MUST share data types and some cannot work with int types

Operator

Name

Example

+

Addition

x + y

-

Subtraction

x - y

*

Multiplication

x * y

/

Division

x / y

%

Modulus

x % y

**

Exponentiation

x ** y

//

Integer division

x // y

Press <shift>-<Enter> keys to execute the script in the jupyter cell.

14.04 / 5.0
2.808
14.04 % 5.0
4.039999999999999
14.04 // 5.0
2.0
x = 5.00
y = 12.98

A = x + y
B = x - y 
C = x * y
print(A)
print(B)
print(C)
17.98
-7.98
64.9
# You do NOT have to work with only values, you can use variables in your operations!

x = "5"
y = 12.98   #float

A = x + y
B = x - y 
C = x * y

print(A)
print(B)
print(C)
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
Cell In[13], line 6
      3 x = "5"
      4 y = 12.98   #float
----> 6 A = x + y
      7 B = x - y 
      8 C = x * y

TypeError: can only concatenate str (not "float") to str
# The type matching fixes it:
x = "5"
y = 12.98  #float

A = x + str(y)

print(A)
type(A)
512.98
str

8.10. String concatenation#

Press <shift>-<Enter> keys to execute the script in the jupyter cell.

A = 'This'
B = 'is'
C = 'a string'

D = A + ' ' + B + ' ' + C + ' indeed'

print(D)
This is a string indeed

8.10.1. Better way is to use the f-string operator#

Press <shift>-<Enter> keys to execute the script in the jupyter cell.

D = f'{A} {B} {C} indeed'

print(D)
This is a string indeed

8.11. Additional Python Operators#

8.11.1. Assignments:#

Operator

Example

Same as…

=

x = 5

x = 5

+=

x += 3

x = x + 3

-=

x -= 3

x = x - 3

*=

x *= 3

x = x * 3

/=

x /= 3

x = x / 3

%=

x %= 3

x = x % 3

//=

x //= 3

x = x // 3

**=

x **= 3

x = x ** 3

8.11.2. Comparisons:#

Operator

Name

Example

==

Equal

x == y

!=

Not equal

x != y

>

Greater than

x > y

<

Less than

x < y

>=

Greater than or equal to

x >= y

<=

Less than or equal to

x <= y

8.11.3. Logical:#

Operator

Example

Same as…

and

Returns True if both statements are true

x < 5 and x < 10

or

Returns True if one of the statements is true

x < 5 or x < 4

not

Reverse the result, returns False if the result is true

not(x < 5 and x < 10)

Press <shift>-<Enter> keys to execute the script in the jupyter cell.

x = 5.0
print(x)

x += 5.0
print(x)

x -= 4.5
print(x)
5.0
10.0
5.5
x = 5
y = "5"

x == y
False
x = 5
y = 16

not(x < 10 or y < 10)
False
d = x<10
print(d)
True

8.12. Python Collections#

There are four collection data types in the Python programming language:

List is a collection which is ordered and changeable. Allows duplicate members.

Tuple is a collection which is ordered and unchangeable. Allows duplicate members.

Set is a collection which is unordered and unindexed. No duplicate members.

Dictionary is a collection which is unordered, changeable and indexed. No duplicate members.
When choosing a collection type, it is useful to understand the properties of that type. Choosing the right type for a particular data set could mean retention of meaning, and, it could mean an increase in efficiency or security.

8.12.1. List#

A list is a collection which is ordered and changeable. In Python lists are written with square brackets. A list can contain different data types. A list can be made by either setting up array with the square brackets or by using the list() constructor.

test_list = [4, 4.0, "4"]

print(test_list)
[4, 4.0, '4']

List items can be accessed through indexing. The list’s index is the numbered placement an element is within the list.

NOTE: Indexing in python starts at 0, not 1. This means that the first item of a list is the 0th index.

You can access items of a list at specific index values, both positive or negative and can even access a range of entries by slicing the list.

test_list[0]
4

In Linux system administration tasks, the list elements usually are file names, user names, package names, device names, commands, etc. They come as strings. Let’s work with a list of files - a.txt, b.txt, c.txt, d.txt, e.txt, f.txt, g.txt.

thislist = ["a.txt", "b.txt", "c.txt", "d.txt", "e.txt", "f.txt", "g.txt"]

print(thislist[3]) # this is the FOURTH item in our list
d.txt

Some great list methods to work with:

Method

Description

append()

Adds an element at the end of the list

clear()

Removes all the elements from the list

copy()

Returns a copy of the list

count()

Returns the number of elements with the specified value

extend()

Add the elements of a list (or any iterable), to the end of the current list

index()

Returns the index of the first element with the specified value

insert()

Adds an element at the specified position

pop()

Removes the element at the specified position

remove()

Removes the item with the specified value

reverse()

Reverses the order of the list

sort()

Sorts the list

# To change the value of a specific item, refer to the index number:
thislist[1] = "new_b.txt"
print(thislist)
print()
['a.txt', 'new_b.txt', 'c.txt', 'd.txt', 'e.txt', 'f.txt', 'g.txt']
# To add an item to the end of the list, use the append() method:
thislist.append("last.txt")
print(thislist)
print()
['a.txt', 'new_b.txt', 'c.txt', 'd.txt', 'e.txt', 'f.txt', 'g.txt', 'last.txt']
# To add an item at the specified index, use the insert() method:
thislist.insert(1, "before_new.txt")
print(thislist)
print()
['a.txt', 'before_new.txt', 'new_b.txt', 'c.txt', 'd.txt', 'e.txt', 'f.txt', 'g.txt', 'last.txt']
# The remove() method removes the specified item:
thislist.remove("d.txt")
print(thislist)
print()
['a.txt', 'before_new.txt', 'new_b.txt', 'c.txt', 'e.txt', 'f.txt', 'g.txt', 'last.txt']
# The del keyword removes the specified index:
del thislist[7]
print(thislist)
print()
['a.txt', 'before_new.txt', 'new_b.txt', 'c.txt', 'e.txt', 'f.txt', 'g.txt']
# You can JOIN two lists by using either '+' or append()

list1 = ["a", "b" , "c"]

list2 = [1, 2, 3]

list3 = list1 + list2

list4 = list2 + list1

print(list3)
print()
print(list4)
['a', 'b', 'c', 1, 2, 3]

[1, 2, 3, 'a', 'b', 'c']
list1 = list1 + ["d"]

print(list1)
['a', 'b', 'c', 'd']

You can take a subset of a list by slicing it,

subset = list1[i_start:i_end:i_step]

where i_start is the index of the first elemnt to take, i_end is the index where you slice it (the element not included), i_step is the selection step, which by default is 1. For example,

subset = list1[0:3:2]

print(subset)
['a', 'c']

8.13. Dictionaries#

A list stores items, but if you want to store items based on specific indicators, you can use a dictionary. A dictionary is accessed based on the “key” and once it finds that key, it will access and use the “value” associated with it. This of the key as the word you want to learn about in an actual dictionary and its definition is its value.

Dictionary items are ordered, changeable, can be of any data type, and does not allow duplicate keys (one can, however, have duplicated values).

Dictionary items are presented in key:value pairs, and can be referred to by using the key name.

Dictionaries are changeable, meaning that we can change, add or remove items after the dictionary has been created.

file_dictionary = {'a.txt':'4K',
                   'b.txt':'2K',
                   'c.txt':'19K'}

print(file_dictionary)
{'a.txt': '4K', 'b.txt': '2K', 'c.txt': '19K'}
# Now that a dictionary has been made, how do you access it?
# The values can be referenced by the keys:
print(file_dictionary['b.txt'])
2K

The dictionary elements can b accessed by method .items()

for key, value in file_dictionary.items():
    print(f"Key: {key}, Value: {value}")
Key: a.txt, Value: 4K
Key: b.txt, Value: 2K
Key: c.txt, Value: 19K

The keys and values can be also accessed by methods .keys() and .values():

file_dictionary.keys()
dict_keys(['a.txt', 'b.txt', 'c.txt'])
file_dictionary.values()
dict_values(['4K', '2K', '19K'])

The values can be referenced by the keys

To loop over all the dictionary elements:

for key in file_dictionary.keys():
    print(file_dictionary[key])
4K
2K
19K

Now its a good moment to talk about loops.

8.14. Loops#

To create a list, you can use a LOOP.

A for loop is used for iterating over a sequence (that is either a list, a tuple, a dictionary, a set, or a string). This is less like the for keyword in other programming languages, and works more like an iterator method as found in other object-orientated programming languages.

With the for loop we can execute a set of statements, once for each item in a list, tuple, set etc.

The types of loops you can work with include:

  • for loops

  • if/else loops, where “if” a condition is met, do A; if another condition is met, do B

  • while loops, where you do A repeatedly until a condition is met

print(list1)
print(list2)

for x in list1:
    list2.append(x)

print(list2)
['a', 'b', 'c', 'd']
[1, 2, 3]
[1, 2, 3, 'a', 'b', 'c', 'd']
list2.clear()
print(list2)
[]
# Add some items to a list using a for loop
thislist

file_list = []

for item in thislist:
    file_list.append(item)
    
print(thislist)
print(file_list)
['a.txt', 'before_new.txt', 'new_b.txt', 'c.txt', 'e.txt', 'f.txt', 'g.txt']
['a.txt', 'before_new.txt', 'new_b.txt', 'c.txt', 'e.txt', 'f.txt', 'g.txt']
thislist

file_list = []

for item in thislist:
    
    if item != "before_new.txt":
    
        file_list.append(item)
    
print(thislist)
print(file_list)
['a.txt', 'before_new.txt', 'new_b.txt', 'c.txt', 'e.txt', 'f.txt', 'g.txt']
['a.txt', 'new_b.txt', 'c.txt', 'e.txt', 'f.txt', 'g.txt']
for i in range( len(file_list) ):
    print(i)
    print(file_list[i])
0
a.txt
1
new_b.txt
2
c.txt
3
e.txt
4
f.txt
5
g.txt
  • You can run a loop within a loop

  • If you want to stop the loop based on a specific condition, use “break”

  • If you want to keep one loop going even if it runs into an issue with another loop, use “continue”

  • Unsure how many times you need to iterate over? Try “range()”

A “Pythonic” way to make lists less bulky is to use list comprehension, which offers a shorter syntax when you want to create a new list based on the values of an existing list.

With list comprehension, you are building a loop in a single line.

list1 = ['a','b','c','d','e']

list2 = [ list1[i] for i in range(len(list1)) ]
print(list2)

list3 = [ list1[i] for i in range(len(list1)) if i!=2 ]
print(list3)
['a', 'b', 'c', 'd', 'e']
['a', 'b', 'd', 'e']

8.15. Conditionals#

a = 5
b = 10
a == b
a == 5
True
output = 'False statement'
if a > 5:
    output = 'true statement'
    s = 23
    st = 'value'
    
elif b == 11:
    output = 'elseif block'
    print(output)

else:
    output = 'entered false block'
    print(output)
entered false block

8.16. Functions#

def f():
    print(f'function f')

Use function in the main code:

f()
function f

Positional arguments:

def f(x, y):
    print(f'x = {x}')
    print(f'y = {y}')
    print(f'sum = {x + y}')
a = 14
b = 36
f(a, b)
x = 14
y = 36
sum = 50

8.16.1. Default parameters:#

def f( x = 10, y = 3 ):
    print(f'x = {x}')
    print(f'y = {y}')
    print(f'sum = {x + y}')
    
# If no input parameters are specified at the function call, the default parameters will be used:
f()
x = 10
y = 3
sum = 13

8.16.2. Immutable arguments: int, float, str, tuples:#

def f(x):
    y = x ** 2
    x = y
    print(f'x in the function: {x}')

x = 5

f(x)

print(f'x in the colling main: {x}')
x in the function: 25
x in the colling main: 5

8.16.3. Mutable arguments:#

def f(x):
    x[0] = '---'

my_list = ['this', 'one', 'will', 'change']

f(my_list)

print(my_list)
['---', 'one', 'will', 'change']

8.16.4. Return statement:#

def compute(x, y):
    s = x + y
    return s

a = 20
b = 30
sum = 40
sum = compute(a,b)

print(sum)
50

8.16.5. Multiple positional argument packing:#

def f(*args):
    print(args)
    print(type(args), len(args))
    for x in args:
         print(x)
f(4,6,8,10,23,34)
(4, 6, 8, 10, 23, 34)
<class 'tuple'> 6
4
6
8
10
23
34
tp=(1,4,5,6,4,6,7,8,10)
f(*tp)
(1, 4, 5, 6, 4, 6, 7, 8, 10)
<class 'tuple'> 9
1
4
5
6
4
6
7
8
10

8.16.6. Calculate area#

Shape Rectangle: \(S = a \cdot b\)

Shape Circle: \(S = \pi \cdot r^2\)

def S(shape,a,b,r):
    if shape == 'rectangle':
        return a * b
    elif shape == 'circle':
        return 3.1415 * r * r
    else:
        print('unknown shape')
Area = S('rectangle', 2,3,0)
print(Area)
6
Area = S('circle', 0, 0, 3)

print(Area)
28.2735

8.16.7. Create a python script#

  • Save the cells in file area.py.

  • Make the file executable and runnable in the bash shell.

  • To make it runnable by python, put this to the top in the file: #!/usr/bin/env  python3:


#!/usr/bin/env  python3

def S(shape,a,b,r):
    if shape == 'rectangle':
        return a * b
    elif shape == 'circle':
        return 3.1415 * r * r
    else:
        print('unknown shape')

Area = S('rectangle', 2,3,0)
print(Area)

Area = S('circle', 0, 0, 3)
print(Area)

  • Import area as a module in the new cell.

import area
  • Eliminate statement execution by using if __name__ == '__main__' directive:

#!/usr/bin/env  python3

def S(shape,a,b,r):
    if shape == 'rectangle':
        return a * b
    elif shape == 'circle':
        return 3.1415 * r * r
    else:
        print('unknown shape')

if __name__ == '__main__':

  Area = S('rectangle', 2,3,0)
  print(Area)

  Area = S('circle', 0, 0, 3)
  print(Area)

  • Move area.py into new directory, Modules.

mkdir Modules
mv area.py Modules
  • Modify sys.path to include directory Modules.

import sys
sys.path.append('Modules')
import area

area.S('circle',0,0,4)
50.264

8.17. Create a class with a method for the area calculation#

The key components of a class file.

class keyword defines the class.

__init__ method is a constructor.

self parameter is a reference to the current instance of the class.

class area:

  def __init__(self,shape, a, b, r):
    self.shape = shape
    self.a  = a
    self.b = b
    self.r = r


  def S(self) -> float:
    if self.shape == 'rectangle':
        return self.a * self.b
    elif self.shape == 'circle':
        return 3.1415 * self.r * self.r
    else:
        print('unknown shape')

In directory Modules, create file areacls.py

The module, class, and the method can be accessed as follows:

from areacls import area
thisarea = area('circle',0,0,3)
S = thisarea.S()
print(S)

8.18. Reading from and writing in files from Python#

  • open() and close() methods

  • Reading files into variables and lists

  • Writing variables and lists into files

  • with statement to read/write and assumed open()/close()

Opening a file for read or write:

f = open(file, mode)

Modes include:

  • “r” - Read - Default value. Opens a file for reading, error if the file does not exist

  • “a” - Append - Opens a file for appending, creates the file if it does not exist

  • “w” - Write - Opens a file for writing, creates the file if it does not exist

  • “x” - Create - Creates the specified file, returns an error if the file exist

In addition to these modes, there are important white space characters that are paired with an “escape” character. You may need to use them to be very specific in how you read or write your files. Examples include:

  • ’ \’ ’ or ’ " ’ maintains quotation marks within a defined string

  • ’ \t ’ is a tab space, which is four spaces in code language

  • ’ \n ’ is a new line, which moves the next string of text to the next line

8.18.1. Writing a list into a file:#

file_list = ['a.txt 4K', 'b.txt 1K', 'c.txt 10K', 'd.txt 1K', 'e.txt 12K', 'f.txt 3K', 'g.txt 6K']

f = open('files.txt', 'w')

for item in file_list:
    f.write(item + "\n" )
    
f.close()

8.18.2. Check if file files.txt was created:#

%ls *.txt
files.txt  passwd.txt  requirements.txt

8.18.3. Reading from a file:#

f = open('files.txt', 'r')

data = f.readlines()

f.close()

print(data)
['a.txt 4K\n', 'b.txt 1K\n', 'c.txt 10K\n', 'd.txt 1K\n', 'e.txt 12K\n', 'f.txt 3K\n', 'g.txt 6K\n']
data = [i.rstrip('\n') for i in data]

print(data)
['a.txt 4K', 'b.txt 1K', 'c.txt 10K', 'd.txt 1K', 'e.txt 12K', 'f.txt 3K', 'g.txt 6K']

8.18.4. Opening, reading, and closing a file in one command:#

with open("files.txt", 'r') as f:
    data = f.readlines()
    
print(data)
['a.txt 4K\n', 'b.txt 1K\n', 'c.txt 10K\n', 'd.txt 1K\n', 'e.txt 12K\n', 'f.txt 3K\n', 'g.txt 6K\n']

8.18.5. Alternative approach with a loop:#

lines = []
with open("files.txt", 'r') as f:
    for line in f: 
        line = line.rstrip('\n') 
        lines.append(line) 
        
print(lines)
['a.txt 4K', 'b.txt 1K', 'c.txt 10K', 'd.txt 1K', 'e.txt 12K', 'f.txt 3K', 'g.txt 6K']