from fastapi import FastAPI, HTTPException from pydantic import BaseModel,Field import pandas as pd import logging # Configure logging logging.basicConfig( level=logging.INFO, # Set the logging level to INFO format="%(asctime)s - %(levelname)s - %(message)s", handlers=[ logging.FileHandler("app.log"), # Log to a file named app.log logging.StreamHandler() # Log to the console ] ) # Create logger instance logger = logging.getLogger(__name__) app = FastAPI() file_path = "D:/backend1/world_population.csv" try: countries_df = pd.read_csv(file_path) # Convert Population and Area to numeric values with error handling countries_df["Population"] = pd.to_numeric(countries_df["Population"]) countries_df["Area"] = pd.to_numeric(countries_df["Area"]) logger.info("CSV file loaded and processed successfully.") except Exception as e: logger.error(f"Failed to load or process CSV file: {e}") raise # Pydantic models for API response class CountryPopulation(BaseModel): country: str population: int class ContinentPopulationResponse(BaseModel): continent: str=Field(description="continent of country") total_population: int total_area: int continent_population_density: float max_population: CountryPopulation min_population: CountryPopulation avg_population: int @app.get("/") def home(): logger.info("Accessed home endpoint.") return {"message": "Welcome to the World Population API"} @app.get("/continent/{continent_name}", response_model=ContinentPopulationResponse) def get_continent_population(continent_name: str): try: logger.info(f"Received request for continent: {continent_name}") # Filter data for the given continent continent_group = countries_df[countries_df["Continent"] == continent_name] continent_group = continent_group.dropna(subset=["Population", "Area"]) if continent_group.empty: logger.warning(f"No data found for continent: {continent_name}") raise HTTPException(status_code=404, detail=f"No data found for continent: {continent_name}") # Calculate total population and total area total_population = int(continent_group["Population"].sum()) total_area = int(continent_group["Area"].sum()) # Handle case where total_area is zero to avoid division by zero if total_area == 0: logger.error(f"Total area is zero for continent: {continent_name}. Cannot calculate population density.") raise HTTPException(status_code=400, detail="Total area is zero. Cannot calculate population density.") # Calculate population density continent_density = total_population / total_area # Find max and min population countries max_row = continent_group.loc[continent_group["Population"].idxmax()] min_row = continent_group.loc[continent_group["Population"].idxmin()] avg_population = int(continent_group["Population"].mean()) logger.info( f"Processed data for continent: {continent_name} | " f"Total Population: {total_population}, Total Area: {total_area}, " f"Population Density: {continent_density:.2f}" ) return ContinentPopulationResponse( continent=continent_name, total_population=total_population, total_area=total_area, continent_population_density=continent_density, max_population=CountryPopulation( country=max_row["Country"], population=int(max_row["Population"]) ), min_population=CountryPopulation( country=min_row["Country"], population=int(min_row["Population"]) ), avg_population=avg_population ) except HTTPException as http_err: # Log and re-raise HTTP-specific exceptions logger.error(f"HTTP exception occurred: {http_err.detail}") raise http_err except Exception as e: # Handle unexpected errors logger.error(f"Unexpected error occurred while processing continent: {continent_name} | Error: {e}") raise HTTPException(status_code=500, detail="An unexpected error occurred while processing your request.")