Reading view

There are new articles available, click to refresh the page.

Reading#Eat the Frog: Ch-2

In continuation from Chapter 1, Chapter 2 starts with how to approach the priority list. Because for a normal person[without any priority like me :-)] every task will be a priority. Unlike that, the author is suggesting an alternative.

It goes like this. Take a piece of paper or use a text editor and name that as “Priorities” and start writing all the tasks that comes to your mind which you wanted to do. Not necessarily in a day, week or month. Just random. For eg: Complete reading a book, finish the assignment, save a minimum amount, practice meditation etc., By the end of this activity, you will have an exhaustive list of task that you wish you could complete.

Next, take one more sheet of paper or open one more text editor and name this as monthly. In here, from the list that you created in “Priorities”, pick up those tasks which could be or has to be completed in the next month. From our example, we can choose “Finish an assignment” and add it to the “monthly” list.

Now the monthly list will be comparatively less than the entire priorities and you have a clear idea of what needs to be done in next 30 days. From here, create one more list for “Weekly”. And do the same exercise of choosing the things that has to or could be completed in next 7 days. And start including them in the weekly list.

Hard part is now complete. From here, connect the things that was described in Chapter#1. Pick up the frog that is bigger to eat and add it to your daily list.

From a larger picture, the moment you knock off one task from daily it creates a ripple effect. That is, it knocks off a task from weekly, then monthly and from the entire priorities. You will accomplished by the end of first week. And if we do this on week 2 we will feel even more happier and accomplished.

This is all about Chapter-2. Once again, this is my understanding and nothing to do with authors narration.

See you again in Chapter-3! Thank you for reading!

Locust ep 5: How to use test_start and test_stop Events in Locust

Locust provides powerful event hooks, such as test_start and test_stop, to execute custom logic before and after a load test begins or ends. These events allow you to implement setup and teardown operations at the test level, which applies to the entire test run rather than individual users.

In this blog, we will

  1. Understand what test_start and test_stop are.
  2. Explore their use cases.
  3. Provide examples of implementing these events.
  4. Discuss how to run and validate the setup.

What Are test_start and test_stop?

  • test_start: Triggered when the test starts. Use this event to perform actions like initializing global resources, starting external systems, or logging test start information.
  • test_stop: Triggered when the test ends. This event is ideal for cleanup operations, aggregating results, or stopping external systems.

These events are global and apply to the entire test environment rather than individual user instances.

Why Use test_start and test_stop?

  • Global Setup: Initialize shared resources, like database connections or external services.
  • Logging: Record timestamps or test details for audit or reporting purposes.
  • External System Management: Start/stop services that the test depends on, such as mock servers or third-party APIs.

Example: Basic Usage of test_start and test_stop

Here’s a basic example demonstrating the usage of these events


from locust import User, task, between, events
from datetime import datetime

# Global setup: Perform actions at test start
@events.test_start.add_listener
def on_test_start(environment, **kwargs):
    print("Test started at:", datetime.now())

# Global teardown: Perform actions at test stop
@events.test_stop.add_listener
def on_test_stop(environment, **kwargs):
    print("Test stopped at:", datetime.now())

# Simulated user behavior
class MyUser(User):
    wait_time = between(1, 5)

    @task
    def print_datetime(self):
        """Task that prints the current datetime."""
        print("Current datetime:", datetime.now())

Running the Example

  • Save the code as locustfile.py.
  • Start Locust -> `locust -f locustfile.py`
  • Configure the test parameters (number of users, spawn rate, etc.) in the web UI at http://localhost:8089.
  • Observe the console output:
    • A message when the test starts (on_test_start).
    • Messages during the test as users execute tasks.
    • A message when the test stops (on_test_stop).

Example: Logging Test Details

You can log detailed test information, like the number of users and host under test, using environment and kwargs


from locust import User, task, between, events

@events.test_start.add_listener
def on_test_start(environment, **kwargs):
    print("Test started!")
    print(f"Target host: {environment.host}")
    print(f"Total users: {environment.runner.target_user_count}")

@events.test_stop.add_listener
def on_test_stop(environment, **kwargs):
    print("Test finished!")
    print("Summary:")
    print(f"Requests completed: {environment.stats.total.num_requests}")
    print(f"Failures: {environment.stats.total.num_failures}")

class MyUser(User):
    wait_time = between(1, 5)

    @task
    def dummy_task(self):
        pass

Observing the Results

When you run the above examples

  • At Test Start: Look for messages indicating setup actions, like initializing external systems or printing start time.
  • During the Test: Observe user tasks being executed.
  • At Test Stop: Verify that cleanup actions were executed successfully.

Reading#Eat the Frog – Ch:1

I always have the challenge of reading. Whether it is technical documentation, general documentation or anything. If I remember correctly, the last time I read something continuously was when I was in my school and college days. And that too nothing extraordinary but weekly magazines like Anandha Vikatan/Kumudham and very rarely newspapers. That got improved when I started my work and regularly read the news headlines from “The Hindu”. That’s all the reading I have got in my entire life. I have this habit of purchasing the books and will think.. One day.. that One day will come and I will become a Pro Reader and I will read all the books. But that did not happened till date.

So I was pouring all these frustration in the “#Kaniyam” IRC chat along with some more concerns like I have trouble planning things. I use to start with one and if I come across something else I will leave whatever I was doing and start doing the new item and it goes on and on. Then Srini from the Kaniyam IRC group suggested various ideas to give a try and one such idea is reading this book called “Eat the Frog”.

I wouldn’t say the book has changed me completely overnight but the practice of reading a few pages continuously gives a sense of satisfaction. I am not saying I have read 20-30 pages continuously instead I planned to complete a chapter whenever i start.

The book as such has got things we often hear or see elsewhere but more importantly it is structured. When I say it is structured, it starts with the topic explanation on why the author has named the book as “Eat the Frog”.

In our daily life if we think eating a frog is one of our primary task. How will one plan. Because eating a frog is not that easy. And that too if you have more than one frog how will one plan to do that. Here the author compares the frog to that of the tasks we have in a day. Not all tasks are difficult as eating a frog. So if we have frogs of different size and the task is to complete eating them all in a day. How will one approach. He will target finishing the bigger one then the next then the next and it goes on. By the time one completes the biggest he will get the confidence to go for the next smaller sized frog.

This analogy works the same way for our daily tasks. Rather than picking the easy ones and save the bulk or harder tasks for a later time, plan to finish the harder or most difficult task first which will help us move with the next difficult task with a lot more confidence.

This was primarily discussed on Chapter 1. After reading this I wanted to see if this approach works. I started implementing it immediately but listing the items it wanted to complete for that day. And in that I sorted those items based on the difficulty(in terms of time). I did not create an exhaustive list rather 4 tasks for that day and out of which 2 are time taking or difficult task.

End of the day I was able to complete the top 2 leaving the remaining 2. I still felt happy because i completed the top 2 which is harder. And moved the pending 2 to next day and kept the priority as top for those 2.

So far it is working and I will continue to write about the other chapters as I complete reading them.

“Let us all start get into the habit of reading and celebrate..happy reading”

Locust ep 4: Why on_start and on_stop are Essential for Locust Users

Locust provides two special methods, on_start and on_stop, to handle setup and teardown actions for individual users. These methods allow you to execute specific code when a simulated user starts or stops, making it easier to simulate real-world scenarios like login/logout or initialization tasks.

In this blog, we’ll cover,

  1. What on_start and on_stop do.
  2. Why they are important.
  3. Practical examples of using these methods.
  4. Running and testing Locust scripts.

What Are on_start and on_stop?

  • on_start: This method is executed once when a new simulated user starts. It’s commonly used for tasks like logging in or setting up the environment.
  • on_stop: This method is executed once when a simulated user stops. It’s often used for cleanup tasks like logging out.

These methods are executed only once per user during the lifecycle of a test, as opposed to tasks that are run repeatedly.

Why Use on_start and on_stop?

  1. Simulating Real User Behavior: Real users often start a session with an action (e.g., login) and end it with another (e.g., logout).
  2. Initial Setup: Some tasks require initializing data or setting up user state before performing other actions.
  3. Cleanup: Ensure that actions like logout are performed to leave the system in a clean state.

Examples

Basic Usage of on_start and on_stop

In this example, we just print on start and `on stop` for each user while running a task.


from locust import User, task, between, constant, constant_pacing
from datetime import datetime


class MyUser(User):

    wait_time = between(1, 5)

    def on_start(self):
        print("on start")

    def on_stop(self):
        print("on stop")

    @task
    def print_datetime(self):
        print(datetime.now())

Locust EP 3: Simulating Multiple User Types in Locust

Locust allows you to define multiple user types in your load tests, enabling you to simulate different user behaviors and traffic patterns. This is particularly useful when your application serves diverse client types, such as web and mobile users, each with unique interaction patterns.

In this blog, we will

  1. Discuss the concept of multiple user types in Locust.
  2. Explore how to implement multiple user classes with weights.
  3. Run and analyze the test results.

Why Use Multiple User Types?

In real-world applications, different user groups interact with your system differently. For example,

  • Web Users might spend more time browsing through the UI.
  • Mobile Users could make faster but more frequent requests.

By simulating distinct user types with varying behaviors, you can identify performance bottlenecks across all client groups.

Understanding User Classes and Weights

Locust provides the ability to define user classes by extending the User or HttpUser base class. Each user class can,

  • Have a unique set of tasks.
  • Define its own wait times.
  • Be assigned a weight, which determines the proportion of that user type in the simulation.

For example, if WebUser has a weight of 1 and MobileUser has a weight of 2, the simulation will spawn 1 web user for every 2 mobile users.

Example: Simulating Web and Mobile Users

Below is an example Locust test with two user types


from locust import User, task, between

# Define a user class for web users
class MyWebUser(User):
    wait_time = between(1, 3)  # Web users wait between 1 and 3 seconds between tasks
    weight = 1  # Web users are less frequent

    @task
    def login_url(self):
        print("I am logging in as a Web User")


# Define a user class for mobile users
class MyMobileUser(User):
    wait_time = between(1, 3)  # Mobile users wait between 1 and 3 seconds
    weight = 2  # Mobile users are more frequent

    @task
    def login_url(self):
        print("I am logging in as a Mobile User")

How Locust Uses Weights

With the above configuration

  • For every 3 users spawned, 1 will be a Web User, and 2 will be Mobile Users (based on their weights: 1 and 2).

Locust automatically handles spawning these users in the specified ratio.

Running the Locust Test

  1. Save the Code
    Save the above code in a file named locustfile.py.
  2. Start Locust
    Open your terminal and run `locust -f locustfile.py`
  3. Access the Web UI
  4. Enter Test Parameters
    • Number of users (e.g., 30).
    • Spawn rate (e.g., 5 users per second).
    • Host: If you are testing an actual API or website, specify its URL (e.g., http://localhost:8000).
  5. Analyze Results
    • Observe how Locust spawns the users according to their weights and tracks metrics like request counts and response times.

After running the test:

  • Check the distribution of requests to ensure it matches the weight ratio (e.g., for every 1 web user request, there should be ~3 mobile user requests).
  • Use the metrics (response time, failure rate) to evaluate performance for each user type.

Locust EP 2: Understanding Locust Wait Times with Complete Examples

Locust is an excellent load testing tool, enabling developers to simulate concurrent user traffic on their applications. One of its powerful features is wait times, which simulate the realistic user think time between consecutive tasks. By customizing wait times, you can emulate user behavior more effectively, making your tests reflect actual usage patterns.

In this blog, we’ll cover,

  1. What wait times are in Locust.
  2. Built-in wait time options.
  3. Creating custom wait times.
  4. A full example with instructions to run the test.

What Are Wait Times in Locust?

In real-world scenarios, users don’t interact with applications continuously. After performing an action (e.g., submitting a form), they often pause before the next action. This pause is called a wait time in Locust, and it plays a crucial role in mimicking real-life user behavior.

Locust provides several ways to define these wait times within your test scenarios.

FastAPI App Overview

Here’s the FastAPI app that we’ll test,


from fastapi import FastAPI

# Create a FastAPI app instance
app = FastAPI()

# Define a route with a GET method
@app.get("/")
def read_root():
    return {"message": "Welcome to FastAPI!"}

@app.get("/items/{item_id}")
def read_item(item_id: int, q: str = None):
    return {"item_id": item_id, "q": q}

Locust Examples for FastAPI

1. Constant Wait Time Example

Here, we’ll simulate constant pauses between user requests


from locust import HttpUser, task, constant

class FastAPIUser(HttpUser):
    wait_time = constant(2)  # Wait for 2 seconds between requests

    @task
    def get_root(self):
        self.client.get("/")  # Simulates a GET request to the root endpoint

    @task
    def get_item(self):
        self.client.get("/items/42?q=test")  # Simulates a GET request with path and query parameters

2. Between wait time Example

Simulating random pauses between requests.


from locust import HttpUser, task, between

class FastAPIUser(HttpUser):
    wait_time = between(1, 5)  # Random wait time between 1 and 5 seconds

    @task(3)  # Weighted task: this runs 3 times more often
    def get_root(self):
        self.client.get("/")

    @task(1)
    def get_item(self):
        self.client.get("/items/10?q=locust")

3. Custom Wait Time Example

Using a custom wait time function to introduce more complex user behavior


import random
from locust import HttpUser, task

def custom_wait():
    return max(1, random.normalvariate(3, 1))  # Normal distribution (mean: 3s, stddev: 1s)

class FastAPIUser(HttpUser):
    wait_time = custom_wait

    @task
    def get_root(self):
        self.client.get("/")

    @task
    def get_item(self):
        self.client.get("/items/99?q=custom")


Full Test Example

Combining all the above elements, here’s a complete Locust test for your FastAPI app.


from locust import HttpUser, task, between
import random

# Custom wait time function
def custom_wait():
    return max(1, random.uniform(1, 3))  # Random wait time between 1 and 3 seconds

class FastAPIUser(HttpUser):
    wait_time = custom_wait  # Use the custom wait time

    @task(3)
    def browse_homepage(self):
        """Simulates browsing the root endpoint."""
        self.client.get("/")

    @task(1)
    def browse_item(self):
        """Simulates fetching an item with ID and query parameter."""
        item_id = random.randint(1, 100)
        self.client.get(f"/items/{item_id}?q=test")

Running Locust for FastAPI

  1. Run Your FastAPI App
    Save the FastAPI app code in a file (e.g., main.py) and start the server

uvicorn main:app --reload

By default, the app will run on http://127.0.0.1:8000.

2. Run Locust
Save the Locust file as locustfile.py and start Locust.


locust -f locustfile.py

3. Configure Locust
Open http://localhost:8089 in your browser and enter:

  • Host: http://127.0.0.1:8000
  • Number of users and spawn rate based on your testing requirements.

4. Run in Headless Mode (Optional)
Use the following command to run Locust in headless mode


locust -f locustfile.py --headless -u 50 -r 10 --host http://127.0.0.1:8000`

-u 50: Simulate 50 users.

-r 10: Spawn 10 users per second.

How to Create & Publish a PHP Package with Composer? – தமிழில்

அக், 13 2024

பிஹெச்பி பொதிகளை பிஹெச்பி கம்போசர்-உடன் உருவாக்க மற்றும் வெளியிடுவது ஒரு நேரடியான வழிமுறை இந்த வழிமுறையை பின்பற்றினால் நாம் எளிமையாக பிஹெச்பி சமூகத்துடன் நமது நிரல்களை பொதிவடிவத்தில் பகிர்ந்துகொள்ளலாம்.

கம்போசர் – (பிஹெச்பி சார்புகளின் நிர்வாகி) – PHP Dependency Manager

தேவையானவை:

உங்களது கணினியில் பின்வருவற்றை நிறுவி இருப்பது அவசியம்.

  • பிஹெச்பி (பதிப்பு 7.4 or அண்மை)
  • கம்பொசர் (அண்மை பதிப்பு)
  • கிட் (அண்மை பதிப்பு)
  • ஒரு கிட் ஹப் கணக்கு
  • பேக்கஜிஸ்ட் கணக்கு

படிகள்:

படி 1: நம்முடைய பொதிக்கான ஒரு கோப்புறையை உருவாக்கி கொள்ளவும்.

mkdir open-tamil
cd open-tamil

படி 2: கம்போசர் பொதியை துவக்குதல்

நம் கணினியில் கம்போசர் பொதியை துவக்க பின்வரும் கட்டளையை பயன்படுத்தவும்.

composer init

மேற்கண்ட கட்டளையை பயன்படுத்தும் கட்டளைவரி இடைமுகம் பின்வரும் கேள்விகளை கேட்கும்

Package name: your-username/my-php-package

Description: A sample PHP package

Author: Your Name <your-email@example.com>

Minimum Stability: stable (or leave blank)

Package Type: library

License: MIT

இந்த கேள்விகளுக்கு விடையளித்த பின்பு பிறசார்புகளை கேட்கும் no கொடுக்கவும்.

இறுதியாக composer.json உருவாக்க தூண்டியில் yes கொடுத்து உருவாக்கி கொள்ளவும்.

படி 3 :

composer.json கோப்பு உருவாக்கிய பிறகு அது பின்வருமாறு தோன்றும்

{
    "name": "your-username/my-php-package",
    "description": "A sample PHP package",
    "type": "library",
    "require": {
        "php": ">=7.4"
    },
    "autoload": {
        "psr-4": {
            "MyPackage\\": "src/"
        }
    },
    "authors": [
        {
            "name": "Your Name",
            "email": "your-email@example.com"
        }
    ],
    "license": "MIT"
}

படி 4

பின்னர் உங்களது குறிமுறையை கிட் பயன்படுத்தி கிட்ஹப்பில் பதிவேற்றவும்.

படி 5

குறியீட்டை கம்போசரில் பதிப்பிக்க பேக்கேஜிஸ்டில் உள்நுழையவும். பின்னர் submit பொத்தானை அழுத்தவும்

submit பொத்தானை அழுத்தியவுடன் பொதியை எற்றும் பக்கம் திறக்கப்பட்டு உங்களது கிட்ஹப் கணக்கில் உள்ள பொதுவாக அனுமதியில் இருக்ககூடிய ரெபொசிடரியின் வலைமுகவரியை உள்ளிட்டு சரிபார்க்கும் பொத்தானை அழுத்தி சரிபார்த்துகொள்ளவும்.

குறிப்பு : கம்போசரை பொறுத்தவகையில் பதிப்பிப்பவர் வென்டார் (vendor) என்று குறிப்பிடப்படுவர். நான் hariharan என்ற வென்டார் பெயரை பயன்படுத்தி இரு பொதிகளை பதிப்பித்துள்ளேன்.

புதிய பொதியை சரிபார்த்த பின் பொதியானது பதிப்பிக்க தயராகிவிடும்.

பார்க்க :

https://packagist.org/packages/hariharan/open-tamil

https://packagist.org/packages/hariharan/thirukural

நிறுவி பார்க்க:

composer require hariharan/thirukural

composer require hariharan/open-tamil

Task#6-New version of integrating the Store Billing app to produce a well formatted pdf file using python

I was so much into using the fpdf module that I almost gave up on this particular task. The challenge I faced is that, I can pass the entire content to the createpdf function but the formatting went completely off track. The other option i was thinking is that send lines one after the other to a text file and finally convert that text file to a pdf. But even that task looked out of my ability. I paused this for a few days and poured in all my frustration not just with this task but with all the other challenges in my IRC channel #kaniyam where I received awesome suggestions from Shrinivasan.T, again not just with the solution to this problem but in general about overcoming the challenges in reading.

Took a deep breath and started fresh and came across a resource where they implemented pdf creation using a different module called reportlab where there was a solution to insert the text to display into a python list and get the entries from the list using a loop and add it to the pdf construct. I was able to finally complete the first step using that module.

Here is the code block

import configparser
import psycopg2
import psycopg2.extras
from reportlab.pdfgen import canvas
from reportlab.pdfbase import pdfmetrics
from reportlab.lib import colors
config = configparser.ConfigParser()
config.read('config.ini')
hostname = config['ConnPostgres']['hostname']
database = config['ConnPostgres']['database']
port_id = config['ConnPostgres']['port_id']
pwd = config['ConnPostgres']['pwd']
username = config['ConnPostgres']['username']
bill=0
final_bill_txt = ''
textlines = []
def fetch_BillAmount(in_item,in_qty):
conn=None
cur=None
try:
conn = psycopg2.connect(
host = hostname,
dbname = database,
user = username,
password = pwd,
port=port_id
)
cur = conn.cursor(cursor_factory=psycopg2.extras.RealDictCursor)
select_script = '''Select ItemCode, ItemName, ItemPrice from StoreItems where ItemCode= %s'''
cur.execute(select_script,(in_item,))
dict_items = dict()
dict_items = cur.fetchall()
for dictItem in dict_items:
bill_amount = in_qty * dictItem['itemprice']
return dictItem['itemname'],bill_amount
except Exception as error:
print(error)
finally:
if conn is not None:
conn.close()
if cur is not None:
cur.close()
def billing():
global bill,textlines
in_item = input('Enter the item code:')
in_qty = int(input('Enter the quantity:'))
item_name,calc_bill = fetch_BillAmount(in_item,in_qty)
bill = bill + calc_bill
print(f'The Bill amount for {in_qty} of {item_name} : ${calc_bill}')
textlines.append(f'The Bill amount for {in_qty} of {item_name} : ${calc_bill}')
def write2Pdf(lsTextline):
pdf = canvas.Canvas('Demo.pdf')
pdf.setFillColorRGB(0,0,255)
pdf.setFont("Courier-Bold",24)
pdf.drawCentredString(290,720,"Shoppers Mart")
pdf.line(30,710,550,710)
text = pdf.beginText(40,680)
text.setFont("Courier",18)
for line in lsTextline:
text.textLine(line)
pdf.drawText(text)
pdf.save()
print('Welcome to Shoppers Mart')
first_login = 'Y' #default initial condition
i=1 #default loop initial value
while i != 0:
if first_login != 'Y':
in_Opt = input('Do you wish to continue shopping?(Y/N)')
if first_login == 'Y' or in_Opt == 'Y':
billing()
first_login = 'N'
else:
print(f'Your total bill amount is ${bill}')
textlines.append(f'Your total bill amount is ${bill}')
print('Thank you for shopping!')
textlines.append('Thank you for shopping!')
write2Pdf(textlines)
break

Task#4- Secure the DB config using configParser

The below program uses configparser module to secure the DB config or the connection parameters. In the earlier programs the DB connections were all exposed and kept in the same program. In this program, DB connection is saved under a different file named “config.ini” and the parameters were called with the help of “ConfigParser”.

import configparser#Note: All lowercase
import psycopg2 #module to connect the postgreSQL DB
import psycopg2.extras #module to fetch the data from DB table in the form of Dictionaries
config = configparser.ConfigParser()#Note:the calling method is a camel case
config.read('config.ini')
in_Item2buy = input('Enter the itemcode required:')
in_ItemQty = int(input('Enter the quantity:'))
hostname = config['ConnPostgres']['hostname']
database = config['ConnPostgres']['database']
port_id = config['ConnPostgres']['port_id']
pwd = config['ConnPostgres']['pwd']
username = config['ConnPostgres']['username']
conn=None
cur=None
try:
conn = psycopg2.connect(
host = hostname,
dbname = database,
user = username,
password = pwd,
port=port_id
)
cur = conn.cursor(cursor_factory=psycopg2.extras.RealDictCursor)
#cur = conn.cursor()
select_script = '''Select ItemCode, ItemName, ItemPrice from StoreItems where ItemCode= %s'''
cur.execute(select_script,(in_Item2buy,))
dict_items = dict()
dict_items = cur.fetchall()
for dictItem in dict_items:
#print(dictItem) #test print statement to verify the dict of items for the given input
bill_amount = in_ItemQty * dictItem['itemprice']
print('The bill amount for ',dictItem['itemname'],':$',bill_amount) # Print the price
#conn.commit() #not required for this program as we are not doing any DML
except Exception as error:
print(error)
finally:
if conn is not None:
conn.close()
if cur is not None:
cur.close()

Task#3c: BillingApp with output in pdf file(not formatted properly)

After many unsuccessful attempts, I was able to send the output from my previous code block to a pdf file. Definitely a huge learning in terms of how to properly import the necessary packages how to troubleshoot the error messages and find out the deprecated syntax and replace with the updated ones etc.,

here is the snapshot of the exceptions i received during the process of fixing

And here I am with a screenshot with no exception mentioned

My final code snippet below:

import psycopg2
import psycopg2.extras
from fpdf import FPDF
from fpdf.enums import XPos, YPos
def fetch_BillAmount(in_item,in_qty):
hostname = 'localhost'
database = 'deptstore'
port_id = 5432
pwd = 'admin@1234'
username = 'postgres'
conn=None
cur=None
try:
conn = psycopg2.connect(
host = hostname,
dbname = database,
user = username,
password = pwd,
port=port_id
)
cur = conn.cursor(cursor_factory=psycopg2.extras.RealDictCursor)
#cur = conn.cursor()
select_script = '''Select ItemCode, ItemName, ItemPrice from StoreItems where ItemCode= %s'''
cur.execute(select_script,(in_item,))
dict_items = dict()
dict_items = cur.fetchall()
for dictItem in dict_items:
#print(dictItem) #test print statement to verify the dict of items for the given input
bill_amount = in_qty * dictItem['itemprice']
return dictItem['itemname'],bill_amount
except Exception as error:
print(error)
finally:
if conn is not None:
conn.close()
if cur is not None:
cur.close()
bill=0
final_bill_txt = ''
def billing():
global bill,final_bill_txt
in_item = input('Enter the item code:')
in_qty = int(input('Enter the quantity:'))
item_name,calc_bill = fetch_BillAmount(in_item,in_qty)
bill = bill + calc_bill
print(f'The Bill amount for {in_qty} of {item_name} : ${calc_bill}')
final_bill_txt = final_bill_txt + (f'The Bill amount for {in_qty} of {item_name} : ${calc_bill}\n')
def write2Pdf(in_text):
pdf = FPDF()
pdf.add_page()
pdf.set_font("helvetica", size = 15)
pdf.cell(200, 10, text = "Shoppers Mart",new_x=XPos.LEFT, new_y=YPos.NEXT, align = 'C')
pdf.cell(200, 10, text = final_bill_txt,new_x=XPos.LEFT, new_y=YPos.NEXT,align = 'L')
pdf.output("ShoppersReceipt.pdf")
print('Welcome to Shoppers Mart')
first_login = 'Y' #default initial condition
i=1 #default loop initial value
while i != 0:
if first_login != 'Y':
in_Opt = input('Do you wish to continue shopping?(Y/N)')
if first_login == 'Y' or in_Opt == 'Y':
billing()
first_login = 'N'
else:
print(f'Your total bill amount is ${bill}')
final_bill_txt = final_bill_txt + (f'\n\n\n\nYour total bill amount is ${bill}\n\n\n\n\n\n''Thank you for shopping!')
print(final_bill_txt)
write2Pdf(final_bill_txt)
#print('Thank you for shopping!')
break

PDF Output:

General: Failure to learn from mistakes!

I have been working on a task where I need to collect input(eg: Item code) from user, query the database to fetch the price and then to calculate the bill amount and print the output. I was able to do this successfully. Then comes the next learning where it was asked to feed this output into a pdf file.

I thought it would be a simple task where we will be importing a package and use that to write the output into a pdf file. I was proved terribly wrong.

I found a link where it was asked to use FPDF as a package to import and use it in the code. When I tried to install on my linux machine i kept getting the below error:

As usual I did not get the signal to use my senses rather my IT mindset to start searching like “unable to install fpdf” 🙂 I went link over link over link but ended up with the same error. It started from 4:45 am this morning and finally around 6 am I decided to learn from “mistakes”. My senses started to work, especially the eyes and the sense of seeing 🙂

I carefully went through the exception, yet my IT brain started to override and asked me to just copy and paste the command from the link. This is classic 🙂

It was mentioned something like this:

If you wish to install a non-Debian packaged Python application,
it may be easiest to use pipx install xyz, which will manage a
virtual environment for you. Make sure you have pipx installed.

Then I tried exactly the same command but this time my brain partially worked it seems so replaced xyz to fpdf:

Thank god. Computers aren’t meant to use abusive language. hehehehe 🙂

Then I went back to the pavillion and started searching other links where they asked to install jinja2( i tried that too). And in the same error message, it was mentioned to consider virtual environment, why to leave that, yes I tried that too.

Somehow I got through installing the virtual environment. But after that, I do not know what to do or interpret the error details. So the failure streak continues

Finally…………………………….

My senses were awaken 🙂 And the brain started to work as if I had an espresso shot 🙂 This time i tried the below

Though it failed again. As I said, “I learnt from mistakes(error message)”. And this happened after that.

Moral of the story:

it was told by many people whom I have interacted so far that always “read through the error message. 99% it has got enough information to change and rerun the code or installation” But because of my inherited IT brain I have avoided that till today. But from today, I am planning to change…and “to learn from mistakes(errors)” always. 🙂

Thanks for reading my funny story! 🙂

Task#3b – Billing application from DB using loop

import psycopg2
import psycopg2.extras
def fetch_BillAmount(in_item,in_qty):
hostname = 'localhost'
database = 'deptstore'
port_id = 5432
pwd = 'admin@1234'
username = 'postgres'
conn=None
cur=None
try:
conn = psycopg2.connect(
host = hostname,
dbname = database,
user = username,
password = pwd,
port=port_id
)
cur = conn.cursor(cursor_factory=psycopg2.extras.RealDictCursor)
#cur = conn.cursor()
select_script = '''Select ItemCode, ItemName, ItemPrice from StoreItems where ItemCode= %s'''
cur.execute(select_script,(in_item,))
dict_items = dict()
dict_items = cur.fetchall()
for dictItem in dict_items:
#print(dictItem) #test print statement to verify the dict of items for the given input
bill_amount = in_qty * dictItem['itemprice']
return bill_amount
except Exception as error:
print(error)
finally:
if conn is not None:
conn.close()
if cur is not None:
cur.close()
bill=0
def billing():
global bill,itemized_bill
in_item = input('Enter the item code:')
in_qty = int(input('Enter the quantity:'))
calc_bill = fetch_BillAmount(in_item,in_qty)
bill = bill + calc_bill
print('Welcome to Shoppers Mart')
first_login = 'Y' #default initial condition
i=1 #default loop initial value
while i != 0:
if first_login != 'Y':
in_Opt = input('Do you wish to continue shopping?(Y/N)')
if first_login == 'Y' or in_Opt == 'Y':
billing()
first_login = 'N'
else:
print_txt = 'Your total Bill amount : ',bill
print('Your total Bill amount : ',bill)
print('Thank you for shopping!')
break

Task#3a – To retrieve the bill amount for a specific store item from database

In this program, the user can get the input about what item is required from the store and how many quantities. Based on the input the dynamic query returns the price of the item selected and the bill amount is calculated and printed.

import psycopg2 #module to connect the postgreSQL DB
import psycopg2.extras #module to fetch the data from DB table in the form of Dictionaries
in_Item2buy = input('Enter the itemcode required:')
in_ItemQty = int(input('Enter the quantity:'))
hostname = 'localhost'
database = 'deptstore'
port_id = 5432
pwd = 'admin@1234'
username = 'postgres'
conn=None
cur=None
try:
conn = psycopg2.connect(
host = hostname,
dbname = database,
user = username,
password = pwd,
port=port_id
)
cur = conn.cursor(cursor_factory=psycopg2.extras.RealDictCursor)
#cur = conn.cursor()
select_script = '''Select ItemCode, ItemName, ItemPrice from StoreItems where ItemCode= %s'''
cur.execute(select_script,(in_Item2buy,))
dict_items = dict()
dict_items = cur.fetchall()
for dictItem in dict_items:
#print(dictItem) #test print statement to verify the dict of items for the given input
bill_amount = in_ItemQty * dictItem['itemprice']
print('The bill amount for ',dictItem['itemname'],':$',bill_amount) # Print the price
#conn.commit() #not required for this program as we are not doing any DML
except Exception as error:
print(error)
finally:
if conn is not None:
conn.close()
if cur is not None:
cur.close()

Task#3- My first python program to connect and retrieve data from DB

import psycopg2 #module to connect the postgreSQL DB
import psycopg2.extras #module to fetch the data from DB table in the form of Dictionaries
hostname = 'localhost'
database = 'deptstore'
port_id = 5432
pwd = 'admin@1234'
username = 'postgres'
conn=None
cur=None
try:
conn = psycopg2.connect(
host = hostname,
dbname = database,
user = username,
password = pwd,
port=port_id
)
cur = conn.cursor(cursor_factory=psycopg2.extras.RealDictCursor)
#cur = conn.cursor()
select_script = '''Select ItemCode, ItemName, ItemPrice from StoreItems'''
cur.execute(select_script)
dict_items = dict()
dict_items = cur.fetchall()
for items in dict_items:
print(items)
#conn.commit() #not required for this program as we are not doing any DML
except Exception as error:
print(error)
finally:
if conn is not None:
conn.close()
if cur is not None:
cur.close()

Task#2a- A simple billing app to use the information stored in a csv file

#simple billing app using csv read functionality
#PRE_REQUISITE: Place the file "StoreItems.csv" in the current Python folder or specify the complete file path
import csv
in_ItemCode = input('Enter the item code:')
in_ItemQty = int(input('Enter the quantity required: '))
with open('StoreItems.csv','r') as file1:
reader1 = csv.DictReader(file1)
for row in reader1:
if row['ItemCode']==in_ItemCode:
print('The bill amount for',row['ItemName'],'is:$',int(row['ItemPrice'])*in_ItemQty)

Task#2: Billing application for a store

create a project – billing application for a grocery store. define the items and prices as a dictionary.get item number and quantity as input.in w while loop, till the itemnumber = 0.for now on the billing application, define the prices as a dictionary. later, read the price data from a CSV file

''' Function to calculate the billing for the purchased item'''
def billing_app():
item_to_buy = int(input('Enter the itemcode[Rice-1011 Dhal-1012 Oil-1013 Spices-1014]: '))
if item_to_buy in dictStoreItems.keys():
qty_to_buy = float(input('Enter the quamtity: '))
print('The total bill amount for ',item_to_buy,': ',qty_to_buy*dictStoreItems[item_to_buy])
else:
print('Invalid Item Code')
dictStoreItems = {1011:15,1022:10,1033:5,1044:3,1055:2}
input('Enter the membership number: ')
first_time_login = 'Y' #used to identify the first time a shopper logging in
i=1 #looping criteria
in_Opt='Y' #defaulting the option to Y for the first time shopping
while i != 0:
if first_time_login != 'Y':
in_Opt = input('Do you wish to continue shopping?(Y/N)')
if in_Opt == 'Y' or first_time_login == 'Y':
billing_app()
first_time_login = 'N'
else:
print('Thank you for shopping!')
break
view raw billing_app.py hosted with ❤ by GitHub
#nested dictionaries
Bill_Total = 0
def billing_app():
item_to_buy = int(input('Enter the itemcode[Rice-1011 Dhal-1012 Oil-1013 Spices-1014]: '))
if item_to_buy in dictStoreItems.keys():
qty_to_buy = float(input('Enter the quamtity: '))
print('The Bill amount for ',dictStoreItems[item_to_buy]['Name'],': $',dictStoreItems[item_to_buy]['UnitPrice']*qty_to_buy)
global Bill_Total
Bill_Total = Bill_Total + dictStoreItems[item_to_buy]['UnitPrice']*qty_to_buy
else:
print('Invalid Item Code')
#below is the nested dictionary containing Product code, name and unit price
dictStoreItems = {1011:{'Name':'Rice','UnitPrice':15},1012:{'Name':'Dhal','UnitPrice':10},1013:{'Name':'Oil','UnitPrice':5},1014:{'Name':'Salt','UnitPrice':3}}
input('Enter the membership number: ')#dummy input
print('****Welcome to Payilagam Shoppers Mart*****')#dummy output
first_time_login = 'Y' #default initial condition
i=1 #default loop initial value
while i != 0:
if first_time_login != 'Y':
in_Opt = input('Do you wish to continue shopping?(Y/N)')
if first_time_login == 'Y' or in_Opt == 'Y':
billing_app()
first_time_login = 'N'
else:
print('Your total Bill amount : ',Bill_Total)
print('Thank you for shopping!')
break

Task#1:Calculator module

Basic calculator app code:

Alternate method by using function/method:

Code repo:

in_Option = input('Enter the option 1.Sum 2.Difference 3.Multiplcation 4.Division:')
in_Param1 = input('Enter the parameter 1:')
in_Param2 = input('Enter the parameter 2:')
def switch(in_Option):
if in_Option == '1':
print('You entered the option for Addition and the sum of the 2 inputs are: ',int(in_Param1)+int(in_Param2))
return
if in_Option == '2':
if in_Param1>in_Param2:
print('You entered the option for difference and the difference of the 2 inputs are: ',int(in_Param1)-int(in_Param2))
return
else:
print('You entered the option for difference and the difference of the 2 inputs are: ',int(in_Param2)-int(in_Param1))
return
if in_Option == '3':
print('You entered the option for Product and the Product of the 2 inputs are: ',int(in_Param1)*int(in_Param2))
return
if in_Option == '4':
print('You entered the option for Division and the Product of the 2 inputs are: ',int(in_Param1)/int(in_Param2))
return
else:
print('Invalid option selected')
return
switch(in_Option)
def calc_app(input, param1, param2):
if input == 1:
print('Sum=',param1+param2)
elif input ==2 and param1 > param2:
print('Difference=',param1-param2)
elif input == 2 and param2 > param1:
print('Difference=',param2 – param1)
elif input == 3:
print('Product=',param1*param2)
elif input ==4:
print('Division=',param1/param2)
in_Option = int(input('Enter the option[1-Add 2-Subtract 3-Multiply 4-Division]: '))
param1 = int(input('Enter the parameter 1:'))
param2 = int(input('Enter the parameter 2:'))
calc_app(in_Option,param1,param2)

❌