<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Usman Abdulkareem ]]></title><description><![CDATA[Usman Abdulkareem ]]></description><link>https://usman186168.hashnode.dev</link><generator>RSS for Node</generator><lastBuildDate>Sun, 30 Aug 2026 18:13:59 GMT</lastBuildDate><atom:link href="https://usman186168.hashnode.dev/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Connect to PostgreSQL with Python]]></title><description><![CDATA[Introduction
In the digital world today, Data is as vital as life. Therefore, the easiness of interacting and extracting data from databases for modeling, visualization, and analytics is important to Data developers in making  data-driven business de...]]></description><link>https://usman186168.hashnode.dev/connect-to-postgresql-with-python</link><guid isPermaLink="true">https://usman186168.hashnode.dev/connect-to-postgresql-with-python</guid><category><![CDATA[Docker]]></category><category><![CDATA[Python]]></category><category><![CDATA[SQL]]></category><category><![CDATA[PostgreSQL]]></category><category><![CDATA[dataanalytics]]></category><dc:creator><![CDATA[Abdulkareem Usman]]></dc:creator><pubDate>Fri, 17 Jun 2022 10:09:02 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1654502473726/zxt8MJjIS.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-introduction">Introduction</h2>
<p>In the digital world today, Data is as vital as life. Therefore, the easiness of interacting and extracting data from databases for modeling, visualization, and analytics is important to Data developers in making  data-driven business decisions.</p>
<h2 id="heading-learning-objectives">Learning Objectives</h2>
<p>In this article, we will learn the following concepts :</p>
<ul>
<li><p>How to connect to a database with python using popular PostgreSQL database adapter, <strong><em>Psycopg</em></strong>. </p>
</li>
<li><p>Perform tasks with DDL and DML statements with <strong><em>psycopg</em></strong>, and gain a high-level understanding of the package. </p>
</li>
<li><p>Finally, utilize the Python package, <strong><em> ipython-sql</em></strong> to run SQL queries directly in a <a target="_blank" href="https://jupyter.org/">Jupyter Notebook</a>.</p>
</li>
</ul>
<p>The full codes for this demonstration can be found in the <a target="_blank" href="https://github.com/UsmanSimple/Docker--PostgreSQL--Python">github</a> repository</p>
<h2 id="heading-prerequisites">Prerequisites</h2>
<p>The following will be needed to flow along with the demonstration:</p>
<ul>
<li><p>Have a source code editor or Python IDE install in your local system like VSCode, PyCharm, Sublime Text, etc.</p>
</li>
<li><p>A good understanding of Python programming language.</p>
</li>
<li><p>A PostgreSQL database installed within your local system or provision with docker.</p>
</li>
<li><p>A basic understanding of SQL commands.</p>
</li>
</ul>
<h2 id="heading-what-is-psycopg">What is Psycopg?</h2>
<p>Psycopg is the most popular PostgreSQL database adapter for the Python programming language. Its main features are the complete implementation of the Python DB API 2.0 specification and the thread safety (several threads can share the same connection). </p>
<h2 id="heading-what-is-ddl-dml-and-tcl">What is DDL, DML and TCL?</h2>
<p><strong>DDL - Data Definition Language:</strong></p>
<p>This is a set of statements that allow users to define or modify data structures and objects such as tables. These include CREATE, ALTER, DROP, RENAME, TRUNCATE.</p>
<p><strong>DML - Data Manipulation Language:</strong></p>
<p>This is a set of statements that allow users to manipulate the objects of a database. These include SELECT, INSERT, UPDATE, and  DELETE.</p>
<p><strong>TCL - Transaction Control Language:</strong></p>
<p>This is a set of statements that allow users to save and manage the transactions issued to the database.
These include COMMIT, ROLLBACK.</p>
<h2 id="heading-connect-to-postgresql-with-python">Connect to PostgreSQL with Python</h2>
<p><strong>Create a virtual environment:</strong></p>
<p>Here, I will use VSCode terminal to create virtual environment for the project. </p>
<p>You can read up this excellent <a target="_blank" href="https://realpython.com/python-virtual-environments-a-primer/">blog</a> to learn how to create, activate and deactivate python virtual environment.</p>
<p>We might encounter error such as the picture below while activating our environment.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1655036573994/sJHv0wWmG.PNG" alt="activate_error.PNG" /></p>
<p>This is because, <strong>PowerShell</strong> by default restricts running scripts unless we change the execution policies. We can change the execution policies by adding<code>-ExecutionPolicy Bypass</code> args. in VScode. We will create a shell profile with these args by adding below in settings.json (ctrl + shift + p and type "settings.json")</p>
<pre><code><span class="hljs-string">"terminal.integrated.profiles.windows"</span>: {
  <span class="hljs-string">"PowerShell"</span>: {
    <span class="hljs-string">"source"</span>: <span class="hljs-string">"PowerShell"</span>,
    <span class="hljs-string">"icon"</span>: <span class="hljs-string">"terminal-powershell"</span>,
    <span class="hljs-string">"args"</span>: [<span class="hljs-string">"-ExecutionPolicy"</span>, <span class="hljs-string">"Bypass"</span>]
  }
},
<span class="hljs-string">"terminal.integrated.defaultProfile.windows"</span>: <span class="hljs-string">"PowerShell"</span>,
</code></pre><p>We can then restart VSCode and the Terminal.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1655068867749/rwBZimMV6.PNG" alt="activate.PNG" /></p>
<p><strong>Install the Python package:</strong></p>
<p>Install the required package, <em>Psycopg2</em> required to connect to the database.</p>
<p>We will install <a target="_blank" href="https://pypi.org/project/psycopg2/"><strong><em>psycopg2-binary</em></strong></a>, as it is stated in the official website that, the binary package is a practical choice for development and testing.</p>
<p>Below code can be used to install the package in the VSCode terminal:</p>
<pre><code>pip <span class="hljs-keyword">install</span> psycopg2-<span class="hljs-built_in">binary</span>
</code></pre><p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1655284553175/fPqQeMCGJ.PNG" alt="pip install.PNG" /></p>
<p><strong>Set up a PostgreSQL database with docker:</strong></p>
<p>We will set up a database with docker-compose command. If you have a PostgreSQL database installed locally, you can follow along. However, if you wish to start, stop and delete databases without prior installation, you could check out the previous article on <a target="_blank" href="https://usman186168.hashnode.dev/how-to-set-up-postgresql-and-pgadmin-with-docker-a-beginner-guide">how to set up postgresql and padmin wth docker</a></p>
<p>Below code can be used to start up our database with docker:</p>
<pre><code>docker<span class="hljs-operator">-</span>compose up
</code></pre><p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1655313646111/bJZOtZMDg.PNG" alt="database set up.PNG" /></p>
<p>Below image shows the database dashboard with pgAdmin
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1655314076380/oGnuZ9T03.PNG" alt="graphics of database.PNG" /></p>
<p><strong>Connect the database with psycopg2:</strong></p>
<p>Here, we will wrap our code with try and except block to catch any error. We will use a variable <strong><em>conn</em></strong> to implement the connect method to connect to the database. Also, we will make sure to apply the <strong><em>close </em></strong> method to exit the database connection. </p>
<p>The connect method open a session  in our database to perform database transactions like DML, DDL, DQL and so on. In order to perform any SQL transaction or statement, we will need to implement the cursor class.</p>
<p><strong>Cursor </strong>  allows Python code to execute PostgreSQL command in a database session. Cursors are created by the connection.cursor() method: they are bound to the connection for the entire lifetime and all the commands are executed in the context of the database session wrapped by the connection. We will also close the cursor when exit the program.</p>
<p>The best way to handle this exception is to put the closure of the <em>conn</em> object and <em>cursor</em> in the finally block, in case error surface in our connection. Also, if the database is not connected and a close method is applied to the connection object, there will be an error in our finally block. Therefore we declare the variables as None, and create an if statement to execute program.</p>
<pre><code><span class="hljs-keyword">import</span> <span class="hljs-title">os</span>

<span class="hljs-title"><span class="hljs-keyword">import</span></span> <span class="hljs-title">psycopg2</span>

<span class="hljs-title">user</span> <span class="hljs-operator">=</span> <span class="hljs-string">'admin'</span>
<span class="hljs-title">password</span> <span class="hljs-operator">=</span> <span class="hljs-string">'password'</span>
<span class="hljs-title">host</span> <span class="hljs-operator">=</span> <span class="hljs-string">'localhost'</span>
<span class="hljs-title">db</span> <span class="hljs-operator">=</span> <span class="hljs-string">'demo_db'</span>
<span class="hljs-title">port</span> <span class="hljs-operator">=</span> 5432

<span class="hljs-title">conn</span> <span class="hljs-operator">=</span> <span class="hljs-title">None</span>
<span class="hljs-title">curr</span> <span class="hljs-operator">=</span> <span class="hljs-title">None</span>

<span class="hljs-title"><span class="hljs-keyword">try</span></span>:

    <span class="hljs-title">conn</span> <span class="hljs-operator">=</span> <span class="hljs-title">psycopg2</span>.<span class="hljs-title">connect</span>(
        <span class="hljs-title">host</span> <span class="hljs-operator">=</span> <span class="hljs-title">host</span>,
        <span class="hljs-title">dbname</span> <span class="hljs-operator">=</span> <span class="hljs-title">db</span>,
        <span class="hljs-title">user</span> <span class="hljs-operator">=</span> <span class="hljs-title">user</span>,
        <span class="hljs-title">password</span> <span class="hljs-operator">=</span> <span class="hljs-title">password</span>,
        <span class="hljs-title">port</span> <span class="hljs-operator">=</span> <span class="hljs-title">port</span>
    )

    <span class="hljs-title">cur</span> <span class="hljs-operator">=</span> <span class="hljs-title">conn</span>.<span class="hljs-title">cursor</span>()

<span class="hljs-title">except</span> <span class="hljs-title">Exception</span> <span class="hljs-title"><span class="hljs-keyword">as</span></span> <span class="hljs-title"><span class="hljs-keyword">error</span></span>:
    <span class="hljs-title">print</span>(<span class="hljs-title"><span class="hljs-keyword">error</span></span>)

<span class="hljs-title">finally</span>:

    <span class="hljs-title"><span class="hljs-keyword">if</span></span> <span class="hljs-title">cur</span> <span class="hljs-title"><span class="hljs-keyword">is</span></span> <span class="hljs-title">not</span> <span class="hljs-title">None</span>:
        <span class="hljs-title">cur</span>.<span class="hljs-title">close</span>()

    <span class="hljs-title"><span class="hljs-keyword">if</span></span> <span class="hljs-title">conn</span> <span class="hljs-title"><span class="hljs-keyword">is</span></span> <span class="hljs-title">not</span> <span class="hljs-title">None</span>:
        <span class="hljs-title">conn</span>.<span class="hljs-title">close</span>()
</code></pre><p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1655315973957/9gro0BcG4.PNG" alt="connect_no_error.PNG" /></p>
<h2 id="heading-perform-sql-transactions">Perform SQL transactions</h2>
<h3 id="heading-perform-ddl-transaction">Perform DDL transaction</h3>
<p>After successful connection, we will perform a DDL transaction by creating a table called employee in the database. We will create a script in our python code the same way, we put up the statement in our graphical interface of databases engine and apply the execute command.</p>
<p>After the execution, for the change to persist and save in the database, we have to apply TCL statement <strong><em>commit</em></strong> method on the conn - connection object made.</p>
<pre><code>create_script = """ <span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">TABLE</span> <span class="hljs-keyword">IF</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">EXISTS</span> employee (
                                    <span class="hljs-keyword">id</span> <span class="hljs-built_in">int</span> PRIMARY <span class="hljs-keyword">KEY</span>,
                                    <span class="hljs-keyword">name</span> <span class="hljs-built_in">varchar</span>(<span class="hljs-number">50</span>) <span class="hljs-keyword">NOT</span> <span class="hljs-literal">NULL</span>,
                                    sex <span class="hljs-built_in">varchar</span>(<span class="hljs-number">6</span>),
                                    salary <span class="hljs-built_in">int</span>,
                                    dept_id <span class="hljs-built_in">varchar</span>(<span class="hljs-number">10</span>)) <span class="hljs-string">"""
cur.execute(create_script)

conn.commit()</span>
</code></pre><p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1655327852951/oisHmSypi.PNG" alt="check_create_statement.PNG" /></p>
<h3 id="heading-perform-dml-transaction">Perform DML transaction</h3>
<p><strong>INSERT STATEMENT</strong></p>
<p>We will perform DML transaction with INSERT command to add some data to the employee table. Also, to avoid unnecessary errors during insertion because of some constraint such as PRIMARY and UNIQUE KEY specified in part of the attributes or columns, it will be require of us to DROP the table, re-create it and insert the data.</p>
<p>We will add a list of tuples of data and implement a for loop to insert each row of data into the table.</p>
<p>Below code can be used for the insertion:</p>
<pre><code>cur.execute(<span class="hljs-string">'DROP TABLE IF EXISTS employee'</span>)

insert_script = <span class="hljs-string">""" INSERT INTO employee (id, name, sex, salary, dept_id) VALUES (%s, %s, %s, %s, %s)"""</span>

insert_values = [(<span class="hljs-number">1</span>, <span class="hljs-string">'Usman'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-number">100000</span>, <span class="hljs-string">'D2'</span>), (<span class="hljs-number">2</span>, <span class="hljs-string">'Esther'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-number">50000</span>, <span class="hljs-string">'D1'</span>),
     (<span class="hljs-number">3</span>, <span class="hljs-string">'Kingsley'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-number">150000</span>, <span class="hljs-string">'D2'</span>), (<span class="hljs-number">4</span>, <span class="hljs-string">'Toyyib'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-number">103000</span>, <span class="hljs-string">'D1'</span>)]

<span class="hljs-keyword">for</span> value <span class="hljs-keyword">in</span> insert_values:
        cur.execute(insert_script, value)
</code></pre><p>We will refresh our table and query the database with pgadmin interface to confirm the insertion of the data into the table.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1655329708138/iw-hBnwZL.PNG" alt="insert_statement.PNG" /></p>
<p><strong>SELECT STATEMENT</strong></p>
<p>Also, let's perform a SELECT transaction within our python code to view the data inserted. We can do this with <strong><em>print (cur.fetchall)</em></strong> method within cursor class. But, let's employ a for loop statement to view the data row-wise.</p>
<pre><code>select_script = <span class="hljs-string">""" SELECT * FROM employee """</span>
cur.execute(select_script)

 <span class="hljs-keyword">for</span> record <span class="hljs-keyword">in</span> cur.fetchall():
      print(record)
</code></pre><p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1655330385153/4zzSjOLUg.PNG" alt="python code insert.PNG" /></p>
<p>Sometimes, we may want to view part of the attributes of the table. Then, we can employ and import a module inside pyscopg2 <strong>extras.DictCursor</strong> to view our data in a dict format, a cursor that keeps a list of column name.</p>
<pre><code><span class="hljs-keyword">from</span> psycopg2.extras <span class="hljs-keyword">import</span> DictCursor
cur = conn.<span class="hljs-keyword">cursor</span>(cursor_factory = DictCursor)

<span class="hljs-keyword">for</span> <span class="hljs-type">record</span> <span class="hljs-keyword">in</span> cur.fetchall():
     print(<span class="hljs-type">record</span>[<span class="hljs-string">'name'</span>], <span class="hljs-type">record</span>[<span class="hljs-string">'sex'</span>], <span class="hljs-type">record</span>[<span class="hljs-string">'salary'</span>])
</code></pre><p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1655331455404/kIEYg7ent.PNG" alt="dictcursor.PNG" /></p>
<p><strong>UPDATE STATEMENT</strong></p>
<p>We will also perform an UPDATE transaction within our python script.</p>
<pre><code>update_script = <span class="hljs-string">""" UPDATE employee SET salary = 1.50 * salary"""</span>
cur.execute(update_script)
</code></pre><p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1655331831515/bN0p9bW5G.PNG" alt="update data.PNG" /></p>
<p>We can also utilize the pgadmin to see the changes in the salary column of the employee table</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1655332263733/N-SL9gA7c.PNG" alt="insert_pgadmin.PNG" /></p>
<p>Finally, we will wrap up the python script with context manager using <strong>with statement</strong>.  A context manager in Python programming sets up a context, runs the code within the context and finally remove the context. 
The advantage of the context manager in this case will be; ensuring that the cursor object is close automatically as well as the connection is being committed after execution of the code. We will manually close the database connection.</p>
<p>Below code show the implementation of context manager.</p>
<pre><code><span class="hljs-comment"># import the libraries</span>
<span class="hljs-keyword">import</span> psycopg2
<span class="hljs-keyword">from</span> psycopg2.extras <span class="hljs-keyword">import</span> DictCursor

<span class="hljs-comment"># the parameters of the database</span>
user = <span class="hljs-string">'admin'</span>
password = <span class="hljs-string">'password'</span>
host = <span class="hljs-string">'localhost'</span>
db = <span class="hljs-string">'demo_db'</span>
port = <span class="hljs-number">5432</span>

conn = <span class="hljs-literal">None</span>
<span class="hljs-keyword">try</span>:

    <span class="hljs-keyword">with</span> psycopg2.connect(
        host = host,
        dbname = db,
        user = user,
        password = password,
        port = port
    ) <span class="hljs-keyword">as</span> conn:

        <span class="hljs-keyword">with</span> conn.cursor(cursor_factory=DictCursor) <span class="hljs-keyword">as</span> cur:

            <span class="hljs-comment"># DDL TRANSACTION</span>
            cur.execute(<span class="hljs-string">'DROP TABLE IF EXISTS employee'</span>)

            create_script = <span class="hljs-string">""" CREATE TABLE IF NOT EXISTS employee (
                                            id int PRIMARY KEY,
                                            name varchar(50) NOT NULL,
                                            sex varchar(1),
                                            salary int,
                                            dept_id varchar(10)) """</span>
            cur.execute(create_script)

            <span class="hljs-comment"># DML STATEMENT OR TRANSACTION</span>
            insert_script = <span class="hljs-string">""" INSERT INTO employee (id, name, sex, salary, dept_id) VALUES (%s, %s, %s, %s, %s)"""</span>

            insert_values = [(<span class="hljs-number">1</span>, <span class="hljs-string">'Usman'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-number">100000</span>, <span class="hljs-string">'D2'</span>), (<span class="hljs-number">2</span>, <span class="hljs-string">'Esther'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-number">50000</span>, <span class="hljs-string">'D1'</span>),
            (<span class="hljs-number">3</span>, <span class="hljs-string">'Kingsley'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-number">150000</span>, <span class="hljs-string">'D2'</span>), (<span class="hljs-number">4</span>, <span class="hljs-string">'Toyyib'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-number">103000</span>, <span class="hljs-string">'D1'</span>)]

            <span class="hljs-keyword">for</span> value <span class="hljs-keyword">in</span> insert_values:
                cur.execute(insert_script, value)

            update_script = <span class="hljs-string">""" UPDATE employee SET salary = 1.50 * salary"""</span>
            cur.execute(update_script)

            select_script = <span class="hljs-string">""" SELECT * FROM employee """</span>
            cur.execute(select_script)

            <span class="hljs-keyword">for</span> record <span class="hljs-keyword">in</span> cur.fetchall():
                print(record[<span class="hljs-string">'name'</span>], record[<span class="hljs-string">'sex'</span>], record[<span class="hljs-string">'salary'</span>])

<span class="hljs-keyword">except</span> Exception <span class="hljs-keyword">as</span> error:
    print(error)

<span class="hljs-keyword">finally</span>:

    <span class="hljs-keyword">if</span> conn <span class="hljs-keyword">is</span> <span class="hljs-keyword">not</span> <span class="hljs-literal">None</span>:
        conn.close()
</code></pre><h2 id="heading-load-csv-file-into-database-with-python-scripts">Load CSV file into database with Python scripts</h2>
<p>A python script can be utilize to ingest CSV file(s) into database. The full code for the script can be found in this <a target="_blank" href="https://github.com/UsmanSimple/Docker--PostgreSQL--Python/blob/master/csv_to_database.py">Github</a> repository. </p>
<p>We must ensure that the CSV file must be in the same directory with the python script with the library installed. </p>
<p>The script will clean the filename and columns to conform to SQL standard by changing the upper case to lower case and remove symbols, change data type to SQL type, create a table with its attributes with the CSV name, convert the date columns to date-time type and finally ingest the file into the database table.</p>
<p>The main function of the Python script is shown below:</p>
<pre><code><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">main</span>(<span class="hljs-params">file_name : str, date_columns:list = []</span>):</span>
    <span class="hljs-string">"""
    This runs the functions altogether and print necessary statement

    Parameters
    -----------
    file_name:  str
                Name of CSV file to be ingested 

    date_columns:   list, optional
                    List of date columns to be convert

    Returns
    ----------

    """</span>

    table_name, df = clean_table_and_col_names(file_name, date_columns)
    col_to_str = change_dtype(df)
    conn = connect(parameters_dict)
    copy_from_csv(
        conn = conn,
        df = df,
        table_name = table_name,
        col_to_str = col_to_str
    )

<span class="hljs-comment"># run this code below</span>
main(<span class="hljs-string">'employees.csv'</span>, [<span class="hljs-string">'HIRE_DATE'</span>])
</code></pre><h2 id="heading-run-sql-in-jupyter-notebooks">Run SQL in Jupyter Notebooks</h2>
<p> This Python package <strong>ipython-sql</strong> is one of the nifty tools to come across as a data practitioner. This allow easiness of data developer to run jupyter notebook as a SQL IDE.</p>
<pre><code>pip <span class="hljs-keyword">install</span> ipython-<span class="hljs-keyword">sql</span>
</code></pre><p>After installing the package, we can now execute any SQL query or procedure directly through the Notebook, and also store the result to a variable for further analysis.</p>
<p>Here are some general connection strings for various databases:</p>
<ul>
<li>PostgreSQL : postgresql://{user}:{password}@{host}:/{db}</li>
<li>MySQL: mysql://{user}:{password}@{host}/{db}</li>
<li>SQLite: sqlite:///name.db</li>
<li>Oracle: oracle://{user}:{password}@{host}:1521/{db}</li>
</ul>
<p>Here, we will use the PostgreSQL database connection string to connect to the database.</p>
<p>We will have to start a new Jupyter notebook session with the command below:</p>
<pre><code>%load_ext <span class="hljs-keyword">sql</span>
</code></pre><p>We will retrieve the data stored in the database's tables using the connection string with the command below:</p>
<pre><code><span class="hljs-comment"># parameters</span>
user = <span class="hljs-string">'admin'</span>
password = <span class="hljs-string">'password'</span>
host = <span class="hljs-string">'localhost'</span>
db = <span class="hljs-string">'demo_db'</span>
port = <span class="hljs-number">5432</span>

connection_str = <span class="hljs-string">f"postgresql://<span class="hljs-subst">{user}</span>:<span class="hljs-subst">{password}</span>@<span class="hljs-subst">{host}</span>/<span class="hljs-subst">{db}</span>"</span>

%sql $connection_str
</code></pre><p>Then, for each query, we will start with <code>%%sql</code> in-line magic to tell the jupyter notebook that we will be running SQL statements.</p>
<p><strong>Let's run some DML command</strong></p>
<p>After the ingestion of the employees CSV file into the database, let's perform some SQL commands on it.</p>
<p><strong>Check the table first five rows:</strong></p>
<p>As we do in pandas, we always check the first five rows with <em>head </em> method. Let's run the SQL query to get the exact result with LIMIT clause.</p>
<pre><code>%%<span class="hljs-keyword">sql</span>

<span class="hljs-keyword">SELECT</span> * <span class="hljs-keyword">FROM</span> employees
<span class="hljs-keyword">LIMIT</span> <span class="hljs-number">5</span>
</code></pre><p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1655392407060/jMHCzN_SC.PNG" alt="five result.PNG" /></p>
<p><strong>Ordering with SQL statement:</strong></p>
<p>This works like sort_order method in Pandas. SQL supports the ordering of columns with <strong>ORDER BY </strong> 
clause. </p>
<p><strong>Question: </strong></p>
<p>What are the names, date and job id of the employees whose salary is greater than 10,000?</p>
<pre><code>%%<span class="hljs-keyword">sql</span> 
<span class="hljs-keyword">SELECT</span> first_name, last_name, hire_date, job_id, salary
<span class="hljs-keyword">FROM</span> employees
<span class="hljs-keyword">WHERE</span> salary &gt;= <span class="hljs-number">10000</span>
<span class="hljs-keyword">ORDER</span> <span class="hljs-keyword">BY</span> salary <span class="hljs-keyword">DESC</span>;
</code></pre><p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1655392625144/Fgzne72AJ.PNG" alt="order by.PNG" /></p>
<p><strong>Grouping with SQL statement:</strong></p>
<p>Transforming a table with aggregate function is one of the importance of groupby method in Pandas. SQL also provides a GROUP BY clause to  achieve this functionality.</p>
<p><strong>Question: </strong></p>
<p>What is the count of staffs in each department?</p>
<pre><code>%%<span class="hljs-keyword">sql</span>

<span class="hljs-keyword">SELECT</span> department_id, COUNT(*) <span class="hljs-keyword">as</span> number_in_dept
<span class="hljs-keyword">FROM</span> employees
<span class="hljs-keyword">GROUP</span> <span class="hljs-keyword">BY</span> department_id 
<span class="hljs-keyword">ORDER</span> <span class="hljs-keyword">BY</span> <span class="hljs-number">2</span> <span class="hljs-keyword">DESC</span>;
</code></pre><p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1655393012402/61mHFqvZ5.PNG" alt="group by.PNG" /></p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>In this article, we have learned how to  connect PostgreSQL database with python, perform DDL and DML SQL transactions, Ingest CSV file into database with scripts, and finally a Python package to run SQL queries in a Jupyter notebook. </p>
<p>We can now use the result after querying our database to make business decision.</p>
<p>Watch out for my forthcoming articles, where I will be discussing how to automate CSV file ingestion to the database using dockerized Python scripts.</p>
<p>I hope you have managed to get something useful from this article.</p>
<p>Let me know if you have any questions or suggestions, and I will be pleased to respond.</p>
<p>Thanks for reading.</p>
<h2 id="heading-further-reading">Further Reading</h2>
<p><a target="_blank" href="https://www.psycopg.org/docs/">Pyscopg documentation</a></p>
<p><a target="_blank" href="https://www.w3schools.com/sql/">SQL commands</a> </p>
]]></content:encoded></item><item><title><![CDATA[How to set up PostgreSQL and pgAdmin with Docker, A beginner Guide.]]></title><description><![CDATA[Introduction
You have probably heard a lot about docker for easy deployment of applications. It can also make our local development processes very fast and problem-free.
Instead of maintaining local installation of databases, we can employ docker and...]]></description><link>https://usman186168.hashnode.dev/how-to-set-up-postgresql-and-pgadmin-with-docker-a-beginner-guide</link><guid isPermaLink="true">https://usman186168.hashnode.dev/how-to-set-up-postgresql-and-pgadmin-with-docker-a-beginner-guide</guid><category><![CDATA[Docker]]></category><category><![CDATA[Databases]]></category><category><![CDATA[Python]]></category><dc:creator><![CDATA[Abdulkareem Usman]]></dc:creator><pubDate>Tue, 07 Jun 2022 06:53:30 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1653996690983/Quavmx8Yb.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-introduction">Introduction</h2>
<p>You have probably heard a lot about docker for easy deployment of applications. It can also make our local development processes very fast and problem-free.
Instead of maintaining local installation of databases, we can employ docker and its services.</p>
<h2 id="heading-learning-objectives">Learning objectives</h2>
<p>This article aims to demonstrate how to set up and run a fully functional platform with PostgreSQL and pgAdmin working on your local machine with the help of docker.</p>
<h2 id="heading-what-is-docker">What is Docker?</h2>
<p>In simple terms, Docker is a software platform or a tool that help to simplify the building, testing, running, managing and distributing applications along with their dependencies with the help of isolated environment known as containers.</p>
<p>It utilizes a concept called, <a target="_blank" href="https://www.docker.com/resources/what-container/">Containerization</a> to create multiple containers for applications in the same environment.</p>
<p>With docker, users can manage infrastructures in the ways applications are managed.</p>
<h2 id="heading-what-is-postgresql-and-pgadmin">What is PostgreSQL and pgAdmin?</h2>
<p><a target="_blank" href="https://www.postgresql.org/about/">PostgreSQL</a> is an Open Source Object-Oriented relational database management system (ORDBMS), a database engine, that uses and implement SQL (Structure Query Language) standards with many features that safely store and scale the most complicated data workloads.</p>
<p><a target="_blank" href="https://www.pgadmin.org/features/">pgAdmin</a> is an Open Source development platform, and a graphical user interface administration tool for the PostgreSQL engine. It is one of the PostgreSQL client tools for manipulating <a target="_blank" href="https://www.ibm.com/cloud/learn/database-schema">schema </a> and data on an instance or multiple instances of existing local or remote PostgreSQL servers.</p>
<h2 id="heading-benefits-of-using-postgresql-with-docker-for-local-development">Benefits of using PostgreSQL with docker for local development.</h2>
<ul>
<li>Ability to start, stop, and remove containers when done with a project without installations and administration.</li>
<li>Easy and Optimal way of working on multiple projects, side by side that depend on slightly different database versions.</li>
<li>There is less confused disorderliness in the development machine.</li>
<li>Experiment with multiple PostgreSQL projects without having a difficult time managing them.</li>
<li>Generally, with docker as a service, if it runs on your machine, given its compatibility and version, it will run for your mate.</li>
</ul>
<h2 id="heading-prerequisites">Prerequisites</h2>
<p>Below are some prerequisites to note before diving into PostgreSQL with docker</p>
<ul>
<li>First, we will need to install <a target="_blank" href="https://docs.docker.com/engine/install/">Docker</a>. I’ll use Docker Desktop for Windows installation for the demonstration.</li>
<li><p>We will need to understand few terms in docker:</p>
</li>
<li><p><strong>Docker Images</strong>: This is a read-only template that contains a set of instructions for creating a container that can run on the Docker platform. Docker-hub has a variety of images. In this tutorial, we will be fetching PostgreSQL and pgAdmin images.</p>
</li>
<li><strong>Docker Compose</strong>: Compose allows defining and running of multi-containers Docker applications. First, we configure Compose’s services by using a YAML file. Afterward, we can start the services after configuration with a single docker-compose command.</li>
<li><p><strong>Docker run</strong>: The docker run command first creates a write-able container layer over the specified image and then starts it using the specific commands.</p>
</li>
<li><p>Also, a basic understanding of how relational databases works would be beneficial.</p>
</li>
</ul>
<h2 id="heading-postgresql-and-pgadmin-with-docker">PostgreSQL and pgAdmin with Docker</h2>
<p>After successful installation of the docker machine, we can now commence our demonstration.
First, As a developer, we make a new directory for every of our project.
The following code can be used to create and change directories:</p>
<pre><code>mkdir postgres_docker <span class="hljs-comment"># make a new directory </span>
<span class="hljs-built_in">cd</span> postgres_docker <span class="hljs-comment"># change to the new directory</span>
</code></pre><p>Now we can open our favorite text editor; in this example, VSCode will be used to demonstrate the tutorial.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1653911238237/WUmxDbNfo.PNG" alt="postgres_docker.PNG" />
<em>Figure 1 :</em>- VScode for code writing and debugging</p>
<p>There are two methods to deploy and run PostgreSQL and pgAdmin with docker.</p>
<h3 id="heading-method-1-docker-run-commands">Method 1 - docker run commands</h3>
<ul>
<li>Create a bridge network:-</li>
</ul>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1654035621855/AXYF6CCRS.png" alt="docker-communication.png" />
<em>Figure 2</em> - Two standalone containers not connected.</p>
<p>Containers can only communicate with one another if they share a network. <strong> Containers that do not share a network cannot connect</strong>. Therefore, we will create a user-defined docker network to ensure communication between the containers while our applications are running in isolation.
Once connected to a user-defined network, the containers can communicate easily using only another container’s IP address or name.</p>
<pre><code>docker network <span class="hljs-keyword">create</span> pg_net # This <span class="hljs-keyword">create</span> network named  pg_net <span class="hljs-keyword">to</span> ascertain communication

docker network ls # This lists <span class="hljs-keyword">all</span> the  networks the Engine <span class="hljs-string">'daemon'</span> knows about
</code></pre><p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1653947484010/RvCKmPX8q.PNG" alt="docker-network.PNG" />
<em>Figure 3 :</em>  docker network output</p>
<ul>
<li>Run the isolated containers with docker-run:-</li>
</ul>
<p>The below codes can be used to run each container individually, and establish a connection between them with the --network specified command.</p>
<pre><code> docker run <span class="hljs-operator">-</span>it \
  <span class="hljs-operator">-</span>e  POSTGRES_USER<span class="hljs-operator">=</span><span class="hljs-string">"admin"</span>  \
  <span class="hljs-operator">-</span>e  POSTGRES_PASSWORD<span class="hljs-operator">=</span><span class="hljs-string">"password"</span> \
  <span class="hljs-operator">-</span>e  POSTGRES_DB<span class="hljs-operator">=</span><span class="hljs-string">"demo_db"</span> \
  <span class="hljs-operator">-</span>v  {PWD}<span class="hljs-operator">/</span>demo_data:<span class="hljs-operator">/</span><span class="hljs-keyword">var</span><span class="hljs-operator">/</span>lib<span class="hljs-operator">/</span>postgresql<span class="hljs-operator">/</span>data \
  <span class="hljs-operator">-</span>p  <span class="hljs-number">5431</span>:<span class="hljs-number">5432</span> \
  <span class="hljs-operator">-</span><span class="hljs-operator">-</span>restart<span class="hljs-operator">=</span>always \
  <span class="hljs-operator">-</span><span class="hljs-operator">-</span>network<span class="hljs-operator">=</span>pg_net \
  <span class="hljs-operator">-</span><span class="hljs-operator">-</span>name pg_data \
  postgres:<span class="hljs-number">13</span>

docker run <span class="hljs-operator">-</span>d \
  <span class="hljs-operator">-</span>e  PGADMIN_DEFAULT_EMAIL<span class="hljs-operator">=</span><span class="hljs-string">"admin@admin.com"</span> \
  <span class="hljs-operator">-</span>e  PGADMIN_DEFAULT_PASSWORD<span class="hljs-operator">=</span><span class="hljs-string">"password"</span> \
  <span class="hljs-operator">-</span>p  <span class="hljs-number">8080</span>:<span class="hljs-number">80</span> \
  <span class="hljs-operator">-</span><span class="hljs-operator">-</span>network<span class="hljs-operator">=</span>pg_net \
  <span class="hljs-operator">-</span><span class="hljs-operator">-</span>name pg_admin \
  dpage<span class="hljs-operator">/</span>pgadmin4
</code></pre><p>Explanation of the parameters in the docker-run:</p>
<ul>
<li><strong>-it</strong>:- This ensures the container run in interactive processes (like a shell).</li>
<li><strong> -e </strong>:- This allows users to configure <strong>environment</strong> variable for Database and pgAdmin superuser authentication.</li>
<li><strong>-v</strong> :- This ensures <strong>volume</strong> mounting of a local directory inside the container for persisting data/files generated by and used by Docker containers.</li>
<li><strong>-p</strong> :- <strong>Publish</strong> a container port 5432 to the localhost machine 5431.</li>
<li><strong>--network</strong> :- User-defined network to ensure easy communication of standalone containers using only another container’s IP address or name.</li>
<li><strong>-d</strong> :- This suggests the container run in the background and only the container ID is printed, i.e <strong>detached</strong> from showing in the cmd prompt.</li>
<li><strong>--name</strong> :- Define a name to ease referencing containers within a Docker network.</li>
<li><strong> --restart</strong> :- A  restart policy for how a container should or should not be restarted on exit.</li>
<li><strong>postgres:13</strong>:- Specify the image to start the container. We use postgres:13, where postgres indicate the image and <strong>13</strong> indicates a version/tag of the software from the docker hub.</li>
<li><strong>-PWD</strong> :- This indicates the full pathname of the current working directory.</li>
</ul>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1653952551190/qOcknGDdw.PNG" alt="postgresql_db.PNG" />
<em>Figure 4 :</em>  The PostgreSQL container with docker run in interactive mode</p>
<p>Also, we can implement a Python library, <a target="_blank" href="https://www.pgcli.com/">pgcli</a>, that serves as an interactive command-line interface for the PostgreSQL database server to confirm the establishment of the database engine.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1653952908412/gz0GVPqZp.PNG" alt="pgcli_docke.PNG" />
<em>Figure 5 :</em>  The pgcli command</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1654037754121/Ep5czOEeU.PNG" alt="pgadmin-detached.PNG" />
<em>Figure 6 :</em>  The pgAdmin container with docker-run in detached mode</p>
<p>After a successful run of the two containers, open http://localhost:8080/, the port number is based on the mapping we configured under pgAdmin docker-run code.</p>
<ul>
<li>Login with your default mail and password to the pgAdmin</li>
<li>Click Add New Server</li>
<li>Insert a name on the General page, Name: db</li>
<li>Click on Connection:<ul>
<li>Hostname/Address: pg_data # name of the container</li>
<li>Username: admin # username of the database</li>
<li>Password: password # password to the database</li>
</ul>
</li>
<li>Save</li>
</ul>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1654038755933/5ihv6tHdO.PNG" alt="db-stuff.PNG" />
<em>Figure 7 :</em>  Database dashboard after successful connection.</p>
<p><strong>Stopping Docker Containers</strong></p>
<p>The code below can be used to list active containers, stop and remove the containers</p>
<pre><code>docker ps

docker <span class="hljs-keyword">stop</span> container_id

docker rm container_id
</code></pre><p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1654039910684/-bL6U5bpx.PNG" alt="docker stop.PNG" />
<em>Figure 8 :</em>  docker command to stop, remove and list containers</p>
<h3 id="heading-method-2-docker-compose-commands">Method 2 - docker-compose commands</h3>
<p>Starting a container one at a time with docker run, creating a communication network between the containers, and writing a command intimidatingly long all add up to stress. An alternative approach can alleviate all the stress.</p>
<p>A  <strong>docker-compose</strong>  command that codes all runtime configuration data in an aptly named YAML file called docker-compose.yaml can be employed to start multiple containers simultaneously. It also helps with the creation of a default network that connects the services.</p>
<p>First, we will utilize an environment variable <em>.env </em> file, a key-value pair, text file that provides a better way to store, secure, and manage our environment variables defined one per one. The format of a <code>.env</code> file is the same under all operating systems, so make working with environment variables uniform across all platforms. Many times our .<code>gitignore</code> files will have <code>.env</code> files to avoid accidentally sharing the file within the git committed files.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1654240874775/lvRBkeO2L.PNG" alt="env file.PNG" />
<em>Figure 9 :</em>  The environment variables in .env file</p>
<p>Below is an example of the services' configuration file in docker-compose.yaml file</p>
<pre><code><span class="hljs-attribute">version</span>: '3.5'

<span class="yaml"><span class="hljs-attr">services:</span>
  <span class="hljs-attr">pg_data:</span> <span class="hljs-comment"># A string that specifies a custom container name, rather than a generated default name</span>
    <span class="hljs-attr">image:</span> <span class="hljs-string">postgres:13</span>  
    <span class="hljs-attr">environment:</span>       
      <span class="hljs-bullet">-</span> <span class="hljs-string">POSTGRES_USER=${POSTGRES_USER}</span> <span class="hljs-comment"># take its value from .env file</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">POSTGRES_PASSWORD=${POSTGRES_PASSWORD}</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">POSTGRES_DB=${POSTGRES_DB}</span>
    <span class="hljs-attr">volumes:</span>            
      <span class="hljs-bullet">-</span> <span class="hljs-string">./demo_data:/var/lib/postgresql/data</span>
    <span class="hljs-attr">ports:</span>             
      <span class="hljs-bullet">-</span> <span class="hljs-string">"5432:5432"</span>
    <span class="hljs-attr">restart:</span> <span class="hljs-string">always</span>

  <span class="hljs-attr">pgadmin:</span>
    <span class="hljs-attr">image:</span> <span class="hljs-string">dpage/pgadmin4</span> 
    <span class="hljs-attr">environment:</span>         
      <span class="hljs-bullet">-</span> <span class="hljs-string">PGADMIN_DEFAULT_EMAIL=${PGADMIN_DEFAULT_EMAIL}</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">PGADMIN_DEFAULT_PASSWORD=${PGADMIN_DEFAULT_PASSWORD}</span>
    <span class="hljs-attr">volumes:</span>           
      <span class="hljs-bullet">-</span> <span class="hljs-string">./pgadmin_data:/var/lib/pgadmin</span>
    <span class="hljs-attr">ports:</span>              
      <span class="hljs-bullet">-</span> <span class="hljs-string">"8080:80"</span>
    <span class="hljs-attr">restart:</span> <span class="hljs-string">always</span>
    <span class="hljs-attr">depends_on:</span>       
      <span class="hljs-bullet">-</span> <span class="hljs-string">pg_data</span>

<span class="hljs-attr">volumes:</span>
  <span class="hljs-attr">demo_data:</span>
  <span class="hljs-attr">pgadmin_data:</span></span>
</code></pre><p>Explanation:</p>
<ul>
<li><p>depends_on: Define the dependencies of services. This allow us to deploy service in order; e.g. postgres -&gt; pgadmin.</p>
</li>
<li><p>services: this codifies an approach of how the image should be running such as database, port number, executable scripts and so on.</p>
</li>
<li><p>image: Specify the image to start the container from. In this case, we are going to use dpage/pgadmin4, without tags, we meant latest version from Docker Hub.</p>
</li>
</ul>
<p><strong> Running Docker compose</strong></p>
<p>First, we will check and validate the YAML file by executing below command in our terminal.:</p>
<pre><code>docker<span class="hljs-operator">-</span>compose config
</code></pre><p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1654041676189/zucnbqF7g.PNG" alt="config.PNG" />
<em>Figure 10 :</em>  The data compose config output.</p>
<p>Next, we will deploy and run the services by executing the command below:</p>
<pre><code>docker<span class="hljs-operator">-</span>compose up <span class="hljs-operator">-</span>d
</code></pre><p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1654241574221/tnfUT-W5F.PNG" alt="docker-compose-up.PNG" />
<em>Figure 11 :</em>  The data-compose up -d output.</p>
<p><strong>Open pgAdmin</strong></p>
<p>After successful running of the docker-compose services, open http://localhost:8080/ on a browser.
Then enter the email and password configured using the environment variable: PGADMIN_DEFAULT_EMAIL and PGADMIN_DEFAULT_PASSWORD.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1654242424727/RyCFd06mw.PNG" alt="admin login.PNG" />
<em>Figure 12 :</em>  pgAdmin login page</p>
<p><strong>Set up Database</strong></p>
<p>Click Add New Server, Insert any Name under General. The value can be anything preferred.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1654242598947/tw_WNb1YE.PNG" alt="General.PNG" />
<em>Figure 13 :</em>  Server name</p>
<ul>
<li>Click on Connection <ul>
<li>Hostname/address: database service name, in our case is pg_data.</li>
<li>Username:  environment variable POSTGRES_USER.</li>
<li>Password: environment variable POSTGRES_PASSWORD.</li>
</ul>
</li>
</ul>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1654242743458/QUu5j4enI.PNG" alt="connection.PNG" />
<em>Figure 14 :</em>  Server connection</p>
<p>And click <strong>Save </strong>to finish creating. Afterward, we can get access to the database dashboard from the sidebar.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1654242816444/qimyh9mrF.PNG" alt="demo_db.PNG" />
<em>Figure 15 :</em>  Database dashboard.</p>
<p><strong>Stopping Data Compose</strong></p>
<p>To stop the Docker Compose service, the below code can be executed: </p>
<pre><code>docker<span class="hljs-operator">-</span>compose down
</code></pre><p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1654243130505/J_CVfEOGj.PNG" alt="docker-compose for postgres.PNG" />
<em>Figure 16 :</em>  docker-compose down output.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>In this guide, we have learned how to use docker run to start PostgreSQL and pgAdmin individually, connect them with a user-defined network for communication, and then use docker-compose to combine them.</p>
<p>We can now use pgAdmin to create and store databases, queries, and tables directly in PostgreSQL, a convenient approach to administering a database. We can also utilize the graphical user interface pgAdmin to import CSV (Comma Separated Values) files into our databases. We can achieve this by writing queries that reference the CSV file path, or by creating a table in pgAdmin and matching the table's column headings to the CSV's columns.</p>
<p>We can also use tools like pgcli, SQLAlchemy, and Psycopg2 to connect to the database from a Python application on our local system. With the Python Pandas package, we'd be able to write queries to tables in our databases and display the results in table format.</p>
<p>Watch out for my forthcoming articles, where I will be discussing how to connect our databases with the libraries aforementioned and use Python scripts to automate CSV file ingestion to the database.</p>
<p>Let me know if you have any questions or suggestions, and I will be pleased to respond.</p>
<p>Thanks for reading.</p>
<p>Connect with me on <a target="_blank" href="https://twitter.com/Usman_186168">Twitter</a> || <a target="_blank" href="https://www.linkedin.com/in/usman-abdulkareem">LinkedIn</a> || <a target="_blank" href="https://github.com/UsmanSimple">Github</a></p>
<h2 id="heading-further-reading">Further Reading</h2>
<p><a target="_blank" href="https://www.ibm.com/cloud/learn/containerization">Containerization</a></p>
<p><a target="_blank" href="https://docs.docker.com/compose/">docker-compose</a></p>
<p><a target="_blank" href="https://docs.docker.com/network/">docker network</a></p>
<p><a target="_blank" href="https://platform.sh/blog/2021/we-need-to-talk-about-the-env/">Environment variable</a></p>
<p><a target="_blank" href="https://youtu.be/fqMOX6JJhGo">Docker Tutorial for beginners</a></p>
]]></content:encoded></item><item><title><![CDATA[Step by step guide to deploying ML models on Flask web application with AWS EC2 Instance.]]></title><description><![CDATA[Introduction
Data scientists create models that represent and predict real-world data, yet about 95% of these models get lost in notebooks. To guarantee that these models meet their requirements for real-world applications, like as within a web frame...]]></description><link>https://usman186168.hashnode.dev/step-by-step-guide-to-deploying-ml-models-on-flask-web-application-with-aws-ec2-instance</link><guid isPermaLink="true">https://usman186168.hashnode.dev/step-by-step-guide-to-deploying-ml-models-on-flask-web-application-with-aws-ec2-instance</guid><category><![CDATA[Machine Learning]]></category><category><![CDATA[web application]]></category><category><![CDATA[deployment]]></category><category><![CDATA[AWS]]></category><category><![CDATA[Cloud]]></category><dc:creator><![CDATA[Abdulkareem Usman]]></dc:creator><pubDate>Tue, 15 Feb 2022 00:02:13 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1644664289040/ZSufMqmq2.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-introduction">Introduction</h2>
<p>Data scientists create models that represent and predict real-world data, yet about<strong> 95%</strong> of these models get lost in notebooks. To guarantee that these models meet their requirements for real-world applications, like as within a web framework or an Android application, they must be deployed effectively so that they can acquire the necessary data and make accurate predictions.</p>
<p>We'll use the cloud (Amazon Web Services) and a Flask application to deploy our machine learning model for better user engagement in this example.</p>
<p>The full codes for this deployment can be found in the <a target="_blank" href="https://github.com/UsmanSimple/ML-Model-Deployment-with-Flask-and-AWS-EC2-Instance">github repository</a></p>
<h3 id="heading-step-by-step-deployment-processes-of-ml-models-on-a-flask-application-with-aws-ec2-instance">Step by Step Deployment Processes of ML Models on a Flask Application with AWS EC2 Instance</h3>
<h4 id="heading-1-creating-a-machine-learning-model">1. Creating a Machine Learning model:</h4>
<p>With Jupyter notebook, creating a machine learning model is simple. We'll use the Life Expectancy Dataset to build a model that can forecast a country's average life expectancy at birth based on a variety of factors. The country, population, GDP, percentage expenditure, total expenditure on health, status, and others are among these characteristics. These datasets were obtained from <a target="_blank" href="https://www.kaggle.com/kumarajarshi/life-expectancy-who">Kaggle datasets</a> and <a target="_blank" href="https://data.worldbank.org/indicator/SP.POP.TOTL">World bank database</a>.</p>
<p>The problem statement in our case study follows the Regression pattern because it produces a numerical estimate. After completing the ML processes of data cleansing, wrangling, exploratory data analysis, outlier elimination, feature engineering, machine learning pipeline, and model building using several algorithms, the <strong>LightGBM </strong> model was found to be the best.</p>
<pre><code><span class="hljs-comment"># import the necessary libraries</span>
<span class="hljs-keyword">import</span> pandas <span class="hljs-keyword">as</span> pd
<span class="hljs-keyword">import</span> numpy <span class="hljs-keyword">as</span> np
<span class="hljs-keyword">import</span> matplotlib.pyplot <span class="hljs-keyword">as</span> plt
<span class="hljs-keyword">import</span> seaborn <span class="hljs-keyword">as</span> sns

<span class="hljs-keyword">from</span> sklearn.preprocessing <span class="hljs-keyword">import</span> OneHotEncoder, LabelEncoder, StandardScaler
<span class="hljs-keyword">from</span> sklearn.model_selection <span class="hljs-keyword">import</span> train_test_split, StratifiedKFold, cross_val_score, KFold
<span class="hljs-keyword">from</span> sklearn.pipeline <span class="hljs-keyword">import</span> make_pipeline

<span class="hljs-keyword">from</span> sklearn.linear_model <span class="hljs-keyword">import</span> LinearRegression
<span class="hljs-keyword">from</span> sklearn.tree <span class="hljs-keyword">import</span> DecisionTreeRegressor
<span class="hljs-keyword">from</span> sklearn.ensemble <span class="hljs-keyword">import</span> RandomForestRegressor, 

<span class="hljs-keyword">from</span> catboost <span class="hljs-keyword">import</span> CatBoostRegressor
<span class="hljs-keyword">from</span> xgboost <span class="hljs-keyword">import</span> XGBRegressor
<span class="hljs-keyword">from</span> lightgbm <span class="hljs-keyword">import</span> LGBMRegressor

<span class="hljs-keyword">from</span> sklearn.metrics <span class="hljs-keyword">import</span> r2_score, mean_squared_error, mean_absolute_error

<span class="hljs-comment">#Load the dataset </span>
countries = pd.read_csv(<span class="hljs-string">'./Data/Metadata_Country.csv'</span>,encoding=<span class="hljs-string">'latin1'</span>) <span class="hljs-comment"># data from world bank</span>
life_expectancy = pd.read_csv(<span class="hljs-string">'./Data/Life Expectancy Data.csv'</span>) <span class="hljs-comment"># kaggle dataset</span>

<span class="hljs-comment"># Machine learning pipeline for algorithm implementation</span>
<span class="hljs-keyword">from</span> collections <span class="hljs-keyword">import</span> OrderedDict
models = OrderedDict([
    ( <span class="hljs-string">"Linear Regression"</span>,       Pipeline([
                                            (<span class="hljs-string">'preprocessor'</span>, preprocessor),
                                            (<span class="hljs-string">'LRegressor'</span>, LinearRegression())])  ),
    ( <span class="hljs-string">"Decision Tree Regressor"</span>, Pipeline([
                                           (<span class="hljs-string">'preprocessor'</span>, preprocessor),
                                            (<span class="hljs-string">'DTRegressor'</span>, DecisionTreeRegressor())])  ),
    ( <span class="hljs-string">"Random Forest Regressor"</span>, Pipeline([
                                           (<span class="hljs-string">'preprocessor'</span>, preprocessor),
                                            (<span class="hljs-string">'RFRegressor'</span>, RandomForestRegressor())])  ),
    ( <span class="hljs-string">"Catboost Regressor"</span>, Pipeline([
                                           (<span class="hljs-string">'preprocessor'</span>, preprocessor),
                                            (<span class="hljs-string">'CatBoostRegressor'</span>, CatBoostRegressor())])  ),
    ( <span class="hljs-string">"Xgboost Regressor"</span>, Pipeline([
                                           (<span class="hljs-string">'preprocessor'</span>, preprocessor),
                                            (<span class="hljs-string">'XGBoostRegressor'</span>, XGBRegressor())])  ),
        ( <span class="hljs-string">"Lightgbm Regressor"</span>, Pipeline([
                                           (<span class="hljs-string">'preprocessor'</span>, preprocessor),
                                            (<span class="hljs-string">'LightgbmRegressor'</span>, LGBMRegressor())])  )

])

<span class="hljs-comment"># Sorting the algorithm by the coefficient of determination "R²"</span>
score_df = pd.DataFrame.from_dict(scores, columns=[<span class="hljs-string">'R²'</span>], dtype = <span class="hljs-string">"float"</span>, orient=<span class="hljs-string">"index"</span>)
score_df.sort_values(by=<span class="hljs-string">"R²"</span>, ascending=<span class="hljs-literal">False</span>)
</code></pre><p>A code snippet from VS code that shows the Jupyter notebook, python libraries and the algorithms implementation.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1644666061385/lu5uWPGNK.png" alt="Best Model.PNG" />
The image above shows the  rank of the algorithms</p>
<h4 id="heading-2-creating-a-pickle-file-to-save-the-model">2. Creating a Pickle file to save the model:</h4>
<p>Pickle is a standard library in python which is used in serializing machine learning algorithms and saving it to file format <code>.pkl</code> in Python.</p>
<pre><code><span class="hljs-keyword">import</span> pickle
<span class="hljs-comment">#save the trained model</span>
pickle.dump(pipeline_LGBM, open(<span class="hljs-string">'models/pipeline_LGBM.pkl'</span>,<span class="hljs-string">'wb'</span>))
</code></pre><h4 id="heading-3-creating-a-website-templates"><strong>3. Creating a Website templates:</strong></h4>
<p>It is necessary to develop a website to collect data from users to make predictions. This folder contains directories, <em>templates</em> - which contains the HTML template and forms that allow users to enter the corresponding variables and see the anticipated average life expectancy - and <em>static </em> - which provides the CSS-styling sheets and JavaScript required for the interface.</p>
<pre><code><span class="hljs-meta">&lt;!DOCTYPE <span class="hljs-meta-keyword">html</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">html</span> <span class="hljs-attr">lang</span>=<span class="hljs-string">"en"</span>&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">head</span>&gt;</span>
    <span class="hljs-comment">&lt;!-- ========== Meta Tags ========== --&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">charset</span>=<span class="hljs-string">"utf-8"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">http-equiv</span>=<span class="hljs-string">"X-UA-Compatible"</span> <span class="hljs-attr">content</span>=<span class="hljs-string">"IE=edge"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"viewport"</span> <span class="hljs-attr">content</span>=<span class="hljs-string">"width=device-width, initial-scale=1"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"description"</span> <span class="hljs-attr">content</span>=<span class="hljs-string">"ML Prediction Page"</span>&gt;</span>

    <span class="hljs-comment">&lt;!-- ========== Page Title ========== --&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">title</span>&gt;</span>ML Prediction page<span class="hljs-tag">&lt;/<span class="hljs-name">title</span>&gt;</span>


    <span class="hljs-comment">&lt;!-- ========== Start Stylesheet ========== --&gt;</span>

    <span class="hljs-tag">&lt;<span class="hljs-name">link</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"{{ url_for('static', filename ="</span><span class="hljs-attr">assets</span>/<span class="hljs-attr">css</span>/<span class="hljs-attr">bootstrap.min.css</span>")}}" <span class="hljs-attr">rel</span>=<span class="hljs-string">"stylesheet"</span> /&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">link</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"{{ url_for('static', filename ="</span><span class="hljs-attr">assets</span>/<span class="hljs-attr">css</span>/<span class="hljs-attr">flaticon-set.css</span>")}}" <span class="hljs-attr">rel</span>=<span class="hljs-string">"stylesheet"</span> /&gt;</span>


<span class="hljs-tag">&lt;/<span class="hljs-name">head</span>&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span>


    <span class="hljs-comment">&lt;!-- Start Banner 
    ============================================= --&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"banner-area text-center text-normal text-light shadow dark bg-fixed"</span> <span class="hljs-attr">style</span>=<span class="hljs-string">"background-image: url('/static/1.jpg');"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"box-table"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"box-cell"</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"container"</span>&gt;</span>
                    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"row"</span>&gt;</span>
                        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"col-md-8 col-md-offset-2"</span>&gt;</span>
                            <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"content"</span>&gt;</span>
                                <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>This App implements Machine Learning to predict results which had been trained with Life Expectancy datasets.<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
                                <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>
                                    The model learns from the data and predicts 96% accuracy.
                                <span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>

                                <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"btn-success btn-sm"</span> <span class="hljs-attr">style</span>=<span class="hljs-string">"border-radius: 16px;"</span> <span class="hljs-attr">onclick</span>=<span class="hljs-string">"location.href='/predict'"</span>&gt;</span>Click Here To Predict<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
                            <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
                        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
                    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
                <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>

            <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-comment">&lt;!-- End Banner --&gt;</span>

    <span class="hljs-comment">&lt;!-- Start Companies Area 

    &lt;!-- jQuery Frameworks
    ============================================= --&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"{{ url_for('static', filename ="</span><span class="hljs-attr">assets</span>/<span class="hljs-attr">js</span>/<span class="hljs-attr">jquery-1.12.4.min.js</span>")}}"&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"{{ url_for('static', filename ="</span><span class="hljs-attr">assets</span>/<span class="hljs-attr">js</span>/<span class="hljs-attr">bootstrap.min.js</span>")}}"&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>



<span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">html</span>&gt;</span>
</code></pre><h4 id="heading-4-creating-a-flask-application">4. Creating a Flask Application:</h4>
<p>Flask is a Python-based web application framework. It has a wide range of options and libraries for creating web applications. It makes it easier to call Restful APIs using Python.</p>
<pre><code># <span class="hljs-keyword">import</span> required libraries
<span class="hljs-keyword">from</span> flask <span class="hljs-keyword">import</span> Flask
<span class="hljs-keyword">from</span> flask <span class="hljs-keyword">import</span> render_template, request, url_for, jsonify
<span class="hljs-keyword">import</span> pickle
<span class="hljs-keyword">import</span> pandas
<span class="hljs-keyword">import</span> os
<span class="hljs-keyword">import</span> numpy 

# Assign parameters such <span class="hljs-keyword">as</span> static folder names- static

STATIC_DIR = os.path.abspath(<span class="hljs-string">'./static'</span>)

<span class="hljs-meta">#initialize the flask app</span>
app = Flask(__name__,static_folder=STATIC_DIR)

# <span class="hljs-keyword">load</span> the data via pickle file <span class="hljs-keyword">for</span> prediction
model = pickle.<span class="hljs-keyword">load</span>(<span class="hljs-keyword">open</span>(<span class="hljs-string">'models/pipeline_LGBM.pkl'</span>,<span class="hljs-string">'rb'</span>)) 

# state the <span class="hljs-keyword">columns</span> <span class="hljs-keyword">for</span> imputing variables
column =[<span class="hljs-string">'country'</span>, <span class="hljs-string">'year'</span>, <span class="hljs-string">'status'</span>, <span class="hljs-string">'adult_mortality'</span>, <span class="hljs-string">'infant_deaths'</span>,
       <span class="hljs-string">'alcohol'</span>, <span class="hljs-string">'percentage_expenditure'</span>, <span class="hljs-string">'hepatitis_b'</span>, <span class="hljs-string">'measles'</span>, <span class="hljs-string">'bmi'</span>,
       <span class="hljs-string">'under-five_deaths'</span>, <span class="hljs-string">'polio'</span>, <span class="hljs-string">'total_expenditure'</span>, <span class="hljs-string">'diphtheria'</span>,
       <span class="hljs-string">'hiv/aids'</span>, <span class="hljs-string">'gdp'</span>, <span class="hljs-string">'thinness__1-19_years'</span>, <span class="hljs-string">'thinness_5-9_years'</span>,
       <span class="hljs-string">'income_composition_of_resources'</span>, <span class="hljs-string">'schooling'</span>, <span class="hljs-string">'region'</span>, <span class="hljs-string">'incomegroup'</span>,
       <span class="hljs-string">'Population'</span>]

# rendering the homepage <span class="hljs-keyword">template</span> <span class="hljs-keyword">with</span> <span class="hljs-keyword">index</span> <span class="hljs-keyword">function</span>
@app.route("/")
def <span class="hljs-keyword">index</span>():
    <span class="hljs-keyword">return</span> render_template("Home.html")

# rendering the predict.html <span class="hljs-keyword">as</span> it contains the parameters needed <span class="hljs-keyword">for</span> the prediction.
# it requires <span class="hljs-keyword">both</span> the <span class="hljs-keyword">GET</span> <span class="hljs-keyword">for</span> the <span class="hljs-keyword">default</span> <span class="hljs-keyword">value</span> prediction <span class="hljs-keyword">and</span> POST request <span class="hljs-keyword">for</span> prediction <span class="hljs-keyword">if</span> pred.html forms <span class="hljs-keyword">is</span> filled <span class="hljs-keyword">by</span> the <span class="hljs-keyword">User</span> 
@app.route(<span class="hljs-string">'/predict'</span>,methods=[<span class="hljs-string">'GET'</span>,<span class="hljs-string">'POST'</span>])
def predict():
    <span class="hljs-string">'''
    For rendering results on HTML GUI
    '''</span>

    #creates the single <span class="hljs-keyword">function</span> <span class="hljs-keyword">for</span> getting data

    req = request.form
    country = req.<span class="hljs-keyword">get</span>("country",default=<span class="hljs-string">'Nigeria'</span>)
    year = <span class="hljs-type">int</span>(req.<span class="hljs-keyword">get</span>("year",default=<span class="hljs-number">2021</span>))
    status = req.<span class="hljs-keyword">get</span>("status",default= <span class="hljs-string">'Developing'</span>)
    adult_mortality = <span class="hljs-type">int</span>(req.<span class="hljs-keyword">get</span>("adult_mortality",default=<span class="hljs-number">343</span>))
    infant_deaths = <span class="hljs-type">int</span>(req.<span class="hljs-keyword">get</span>("infant_deaths",default=<span class="hljs-number">72</span>))
    alcohol = <span class="hljs-type">float</span>(req.<span class="hljs-keyword">get</span>("alcohol",default=<span class="hljs-number">13</span>))
    percentage_expenditure = <span class="hljs-type">float</span>(req.<span class="hljs-keyword">get</span>("percentage_expenditure",default=<span class="hljs-number">2300</span>))
    hepatitis_b = <span class="hljs-type">float</span>(req.<span class="hljs-keyword">get</span>("hepatitis_b",default=<span class="hljs-number">88</span>))
    measles = <span class="hljs-type">float</span>(req.<span class="hljs-keyword">get</span>("measles",default=<span class="hljs-number">6718</span>))
    bmi = <span class="hljs-type">float</span>(req.<span class="hljs-keyword">get</span>("bmi",default=<span class="hljs-number">25</span>))
    under_five_deaths = <span class="hljs-type">int</span>(req.<span class="hljs-keyword">get</span>("under_five_deaths",default=<span class="hljs-number">114</span>))
    polio = <span class="hljs-type">float</span>(req.<span class="hljs-keyword">get</span>("polio",default=<span class="hljs-number">80</span>))
    total_expenditure = <span class="hljs-type">float</span>(req.<span class="hljs-keyword">get</span>("total_expenditure",default=<span class="hljs-number">7</span>))
    diphtheria = <span class="hljs-type">float</span>(req.<span class="hljs-keyword">get</span>("diphtheria",default=<span class="hljs-number">24</span>))
    hiv_aids = <span class="hljs-type">float</span>(req.<span class="hljs-keyword">get</span>("hiv_aids",default=<span class="hljs-number">100</span>))
    gdp = <span class="hljs-type">float</span>(req.<span class="hljs-keyword">get</span>("gdp",default=<span class="hljs-number">480000</span>))
    thinness_10_19_years = <span class="hljs-type">float</span>(req.<span class="hljs-keyword">get</span>("thinness_10_19_years",default=<span class="hljs-number">13.4</span>))
    thinness_5_9_years = <span class="hljs-type">float</span>(req.<span class="hljs-keyword">get</span>("thinness_5_9_years",default=<span class="hljs-number">13.2</span>))
    income_composition_of_resources = <span class="hljs-type">float</span>(req.<span class="hljs-keyword">get</span>("income_composition_of_resources",default=<span class="hljs-number">0.52</span>))
    schooling = <span class="hljs-type">float</span>(req.<span class="hljs-keyword">get</span>("schooling",default=<span class="hljs-number">10.9</span>))
    region = req.<span class="hljs-keyword">get</span>("region",default=<span class="hljs-string">'Sub-Saharan Africa'</span>)
    incomegroup = req.<span class="hljs-keyword">get</span>("incomegroup",default=<span class="hljs-string">'Lower middle income'</span>)
    population = <span class="hljs-type">float</span>(req.<span class="hljs-keyword">get</span>("population",default=<span class="hljs-number">214140000</span>))


    #storing the data <span class="hljs-keyword">in</span> <span class="hljs-keyword">array</span> <span class="hljs-keyword">format</span>
    <span class="hljs-keyword">array</span> = numpy.<span class="hljs-keyword">array</span>([country,year,status,adult_mortality,infant_deaths, alcohol,percentage_expenditure, hepatitis_b, measles, bmi, under_five_deaths, polio, total_expenditure,diphtheria, hiv_aids, gdp, thinness_10_19_years, thinness_5_9_years, income_composition_of_resources, schooling, region, incomegroup, population]).reshape(<span class="hljs-number">1</span>,<span class="hljs-number">23</span>)

    #creates a dataframe <span class="hljs-keyword">to</span> hold the data
    data = pandas.DataFrame(data=<span class="hljs-keyword">array</span>,<span class="hljs-keyword">columns</span>=<span class="hljs-keyword">columns</span>)

    #predict <span class="hljs-keyword">over</span> the features gotten <span class="hljs-keyword">from</span> the <span class="hljs-keyword">user</span> <span class="hljs-keyword">with</span> the model
    prediction = model.predict(data)
    output = round(prediction[<span class="hljs-number">0</span>])

    #<span class="hljs-keyword">passing</span> <span class="hljs-keyword">value</span> gotten <span class="hljs-keyword">to</span> Predict html <span class="hljs-keyword">template</span> <span class="hljs-keyword">for</span> rendering
    <span class="hljs-keyword">return</span> render_template("Predict.html",prediction_text=<span class="hljs-string">'The Average life expectancy for {} in year {} is {} years'</span>.format(country, year, output))    

# port <span class="hljs-keyword">values</span> changes <span class="hljs-keyword">as</span> we run <span class="hljs-keyword">on</span> <span class="hljs-keyword">local</span> <span class="hljs-keyword">server</span> <span class="hljs-keyword">and</span> <span class="hljs-keyword">in</span> the cloud

<span class="hljs-keyword">if</span> __name__ == <span class="hljs-string">'__main__'</span>:
   app.run(host = <span class="hljs-string">'0.0.0.0'</span>, port = <span class="hljs-number">8080</span>) # cloud
</code></pre><p>To run this in our local environment, navigate to the directory using <strong>CMD- command prompt</strong> and type python <code>app.py</code>.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1644709755120/AcIEBMI5G.png" alt="cmd run.PNG" /></p>
<h4 id="heading-5-creating-an-aws-account">5. Creating an AWS account:</h4>
<p>Once our ML models have been deployed successfully locally, we will move on to our main goal: leveraging cloud services to deploy our ML models via AWS. We'll need to register and create an AWS account. We will acquire a year of free tier service by using our credit card information. This will be beneficial in accomplishing the task at hand.</p>
<p>After successfully registering, we must sign in with our user ID to access the AWS Management Console.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1644711195487/M2lRTtoit.png" alt="AWS Console.PNG" /></p>
<h4 id="heading-6-downloading-the-necessary-softwares"><strong>6. Downloading the Necessary Softwares:</strong></h4>
<p>To accomplish our aim, there is a need to download <strong>two</strong> software required to ensure our application runs successfully by connecting our local environment with AWS EC2 Instance. These includes:</p>
<h5 id="heading-i-putty"><strong>I. PuTTy:</strong></h5>
<p>This is an open-source free terminal emulator, serial interface, and network file transfer program. Its primary advantage is to allow users to run supported protocols, including SSH and Telnet, remotely.
This comes with another open-source networking client <strong>PuTTygen</strong> -  a key generator tool for creating pairs of public and private SSH keys. This is used to convert our private SSH key from PEM file to PPK file.</p>
<p>After successfully installation, you can search for PuTTygen in your local machine as it looks like the image below</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1644712647615/LMKh9ddBC.png" alt="PuTTygen.PNG" /></p>
<h5 id="heading-ii-winscp"><strong>II. WinSCP:</strong></h5>
<p>This is a popular free SFTP and FTP client, a powerful file manager for Windows. It offers an easy-to-use GUI to secure files transfer between a local and remote computer using multiple protocols: Amazon S3, FTP, FTPS, SCP, SFTP, or WebDAV.  The application looks like the image below after successful installation.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1644713013748/ISzAuauZ0.png" alt="WinSCP.PNG" /></p>
<h4 id="heading-7-creating-an-aws-ec2-instance">7. Creating an AWS EC2 Instance:</h4>
<p>A search for EC2 Instance can be done through the AWS Management Console. The image below depicts the AWS EC2 Dashboard.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1644713828654/iOxlD27v5.png" alt="EC2 Dashboard.PNG" /></p>
<p>The following steps will ensure a successful launch of an AWS EC2 Instance.</p>
<h5 id="heading-i-choosing-the-ami-template"><strong>I. Choosing the AMI template</strong>:</h5>
<p>AMI - Amazon Machine Image is a template that contains the software configuration (OS), application server and applications required to launch EC2 Instance. In this case, we are going to be choosing the free tier template- <strong>Ubuntu Server 20.04 LTS (HVM), SSD Volume Type</strong>.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1644714302857/FkvdoEpdJ.png" alt="AMI.PNG" /></p>
<h5 id="heading-ii-choosing-an-instance-type"><strong>II. Choosing an Instance Type</strong>:</h5>
<p>An instance type that suit our free tier will be chosen to avoid charges from our credit cards. Below is an image that shows a free tier instance type- <strong>t2 micro eligible</strong>.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1644714889733/5hgmnpHk2.png" alt="Instance.PNG" /></p>
<h5 id="heading-iii-configuring-the-security-group"><strong>III. Configuring the Security Group</strong>:</h5>
<p>In AWS, security groups are the foundation of network security. They manage the flow of traffic into and out of the EC2 instance.
We'll skip to the security group setting because the other default steps are sufficient for our deployment.
Because we want our program to operate on several screens with the host-name, we must change the type to <strong>All traffic</strong> and the source to <strong>Anywhere</strong> in this situation.
The configuration is shown in the image below.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1644715666274/CIG6fvJmT.png" alt="Configuration.PNG" /></p>
<h5 id="heading-iv-reviewing-and-launching"><strong>IV. Reviewing and Launching:</strong></h5>
<p>We inspect the processes and launch our Instance after carefully configuring the security group. Here, we'll create a new key pair that will allow us to connect to the instance securely. We'll rename it to our liking, then download the key pair and store it in the project's directory folder. The graphic depicts key-pair creation, renaming, and downloading.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1644716456302/4UzXL8nio.png" alt="Review.PNG" /></p>
<h5 id="heading-v-ec2-instance-launch-successfully"><strong>V. EC2 Instance launch successfully</strong>:</h5>
<p>We'll proceed to start the EC2 instance, which may take a few seconds. In the EC2 Dashboard, here's a screenshot of a successful launch of an EC2 Instance.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1644716856194/dmmy6BJeX.png" alt="Image launched.PNG" /></p>
<h4 id="heading-8-creating-a-private-key-ppk-file-with-puttygen"><strong>8. Creating a Private Key PPK File with PuTTygen: </strong></h4>
<p>We'll create a private PPK file by converting the PEM file that was downloaded when the instance was launched and loading it with PuTTygen. To retrieve our PEM file from our project folder, load and store the private key generated into our folder, we indicate that all files are presented.
The screenshot below depicts the creation and saving of the PuTTygen private key.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1644717796435/boop7QmSA.png" alt="Load PEM.PNG" /></p>
<h4 id="heading-9-securing-transfer-of-project-files-via-winscp"><strong>9. Securing Transfer of project files via WinSCP:</strong></h4>
<p>WinSCP, as previously stated, aids in the secure transfer of files from a local workstation to a remote computer. This will allow us to drag and drop the files/codes we need into the EC2 Instance we've just established.
To begin, we'll start WinSCP, which will prompt us to provide a host name.</p>
<p>Second, we'll get the host name from the EC2 dashboard by clicking on the <strong>connect tags</strong>, then copy and paste the Public DNS from the <strong>SSH client</strong>. In WinSCP, we'll use this as our host name.</p>
<p>The images below show the EC2 Dashboard's imputation of the host name.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1644718926906/IBWiId3K3.png" alt="instance connect.PNG" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1644718941294/SoVasChDw.png" alt="WinSCP host.PNG" /></p>
<p>Now we'll go to WinSCP's <strong>Advanced Site Settings</strong>, find SSH, and click on Authentication to load our private key PPK file generated with PuTTygen.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1644719558995/-oE0KELhB.png" alt="Authentication.PNG" /></p>
<p>After that, we select Ok, Create a Username. For my user name, I went with ubuntu. After that, we log in to connect to our Ubuntu server. We also choose our code files by dragging and dropping them into the WinSCP windows on the right side. The amount of time it takes to transfer files is determined by their size. The <code>requirement.txt</code> file is included in these files to allow the installation of the python libraries required to execute the model.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1644721362878/MouvR7RW3.png" alt="file transfer.PNG" /></p>
<p><strong>Note</strong>:
When deploying our model outside of our local system, the IP address and Port number in the Flask app python code must be modified from the defaults of '127.0.0.1' and '5000' to '0.0.0.0' and '8080' to enable smooth execution of the <code>app.py</code> in the cloud using PuTTy terminal.</p>
<h4 id="heading-10-installing-the-required-libraries-with-putty"><strong>10. Installing the required libraries with PuTTy:</strong></h4>
<p>To begin the configuration of the PuTTy app, we will locate it on our system. We'll start by imputing our hostname, as we did before, and then name the Saved Session. Go to the SSH, locate the Auth and load the saved private PPK file.  After that, we go to Session category to save the name, click on it, and open it with PuTTY.
The configuration, name, and opening of the saved file are shown in the image below.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1644722163194/0OM4TnVeK.png" alt="putty saved.PNG" /></p>
<p>We'll communicate with our terminal to confirm that all essential files are uploaded successfully. The screenshot below shows how to use the Git bash to interact with Ubuntu Server.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1644722420054/Iy15ArAlu.png" alt="ubuntu checked.PNG" /></p>
<p>We must first update and install python with the command below to successfully install our libraries into our Ubuntu cloud server.</p>
<pre><code>sudo apt<span class="hljs-operator">-</span>get update <span class="hljs-operator">&amp;</span><span class="hljs-operator">&amp;</span> sudo apt<span class="hljs-operator">-</span>get install python3<span class="hljs-operator">-</span>pip
</code></pre><p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1644723343409/n4vJhPxZk.png" alt="ubuntu 2.PNG" /></p>
<p>Also, to install the required python libraries needed to run the model i.e <code>requirement.txt</code> file, we can execute this by running the command.</p>
<pre><code><span class="hljs-selector-tag">python</span> <span class="hljs-selector-tag">install</span> <span class="hljs-selector-tag">-r</span> <span class="hljs-selector-tag">requirement</span><span class="hljs-selector-class">.txt</span>
</code></pre><p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1644723549785/7Ts_1nb0W.png" alt="ubuntu 3.PNG" /></p>
<h4 id="heading-11-running-the-flask-application-in-the-ubuntu-terminal"><strong>11. Running the Flask application in the ubuntu terminal:</strong>:</h4>
<p>Now that our libraries have been installed successfully, we can execute the program by typing the following command in the terminal.</p>
<pre><code><span class="hljs-selector-tag">python3</span> <span class="hljs-selector-tag">app</span><span class="hljs-selector-class">.py</span>
</code></pre><p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1644724008122/gO3ziQ88g.png" alt="python app.PNG" /></p>
<p>The application has now begun to run. Then, to view our application, we'll go to the EC2 dashboard and locate the connect tags, then use the SSH client to copy the Public DNS.</p>
<p>The URL for our application will be Public DNS + port 8080, as seen in the example below:</p>
<pre><code><span class="hljs-attribute">ec2</span>-<span class="hljs-number">34</span>-<span class="hljs-number">201</span>-<span class="hljs-number">245</span>-<span class="hljs-number">241</span>.compute-<span class="hljs-number">1</span>.amazonaws.com:<span class="hljs-number">8080</span>
</code></pre><p>The home web page of the application is shown below:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1644725633945/S5AGhUi6C.png" alt="webpage.PNG" /></p>
<p>The prediction web page of the application is display as the snapshot below:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1644725825851/O8vpiyeZf.png" alt="prediction.PNG" /></p>
<h4 id="heading-12-final-launch-of-the-application"><strong>12. Final launch of the application:</strong></h4>
<p>It was observed that if the terminal closed, and a new page was opened to restart the application, an error occurred. The following error surfaced::</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1644726359249/_NG-EI-xF.png" alt="error.PNG" /></p>
<p>To resolve this problem, we'll need to employ <strong>GNU Screen</strong>, a full-screen window manager that divides a physical terminal into numerous processes, most commonly interactive shells. Our application will continue to operate even if the window is not visible after disconnection, and our server will remain active by establishing numerous displays even when the git bash terminal is closed.</p>
<p>When the code below is run, it allows the URL to be opened in several browser pages.</p>
<pre><code><span class="hljs-selector-tag">screen</span> <span class="hljs-selector-tag">-R</span> <span class="hljs-selector-tag">deploy</span> <span class="hljs-selector-tag">python3</span> <span class="hljs-selector-tag">app</span><span class="hljs-selector-class">.py</span>
</code></pre><p>The code is implemented in the git bash terminal as seen in the image below.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1644726894111/IpsxHO6o9.png" alt="screen.PNG" /></p>
<h4 id="heading-brief-summary">Brief summary:</h4>
<p>I learned the following from this writing: </p>
<ul>
<li><p>The steps involved in performing an end-to-end machine learning project.</p>
</li>
<li><p>Using the pickle python package to save a machine learning model as a ".pkl" file.</p>
</li>
<li><p>A small-scale web application using the Flask back-end python library.</p>
</li>
<li><p>The processes for launching an Amazon Web Services EC2 instance.</p>
</li>
<li><p>Additional software such as PuTTy and WinSCP are introduced for successful file deployment and transfer from a local machine to a remote computer.</p>
</li>
<li><p>Using the Git bash Ubuntu terminal to install libraries and execute the flask application.</p>
</li>
</ul>
<h4 id="heading-conclusion">Conclusion:</h4>
<p>In this way, we can leverage the cloud services (AWS EC2 Instance) and flask web application to deploy our Machine learning model.</p>
<p>Thanks for reading my article. I would very much appreciate your feedback, suggestions, and critics of my approach to writing. I'm open to collaborations that will further increase my knowledge and growth in ML. Feel free to connect with me on <a target="_blank" href="https://www.linkedin.com/in/usman-abdulkareem/">LinkedIn</a>.</p>
]]></content:encoded></item></channel></rss>