Connecting to PostgreSQL Using Python - A Comprehensive Guide

2 minute read

If youโ€™re working with PostgreSQL databases in your projects, handling connections efficiently and securely is essential. Hereโ€™s a step-by-step breakdown of a Python class that reads credentials from a JSON file and returns SQL query results as a pandas DataFrame.


๐Ÿ“š Key Components of the PostgresConnector Class

This class handles:

  • Secure loading of credentials from a JSON file.
  • Connection management with PostgreSQL using psycopg2.
  • Error logging for better debugging.
  • Query execution with pandas for data analysis.

๐Ÿ”ง Full Python Code (with explanations)

import psycopg2  # PostgreSQL adapter for Python
import pandas as pd  # Data analysis library
import json  # For reading configuration files
import logging  # For logging errors

# Configure logging to track errors in a log file
logging.basicConfig(filename='db_connector.log', level=logging.ERROR, format='%(asctime)s - %(levelname)s - %(message)s')

class PostgresConnector:
    def __init__(self, config_file):
        """
        Initialize the PostgreSQL connection using a JSON config file.
        """
        self.config_file = config_file
        self.conn = None  # Connection placeholder
        self.credentials = self._read_credentials()

    def _read_credentials(self):
        """
        Read database credentials from a JSON file.
        """
        try:
            with open(self.config_file, 'r') as file:
                return json.load(file)
        except Exception as e:
            logging.error(f"Error reading the configuration file: {e}")
            print(f"Error reading the configuration file: {e}")
            return None

    def connect(self):
        """
        Establish connection to PostgreSQL database using credentials from the JSON file.
        """
        if not self.credentials:
            print("No valid credentials found. Check your JSON config file.")
            return

        try:
            self.conn = psycopg2.connect(
                host=self.credentials['host'],
                port=self.credentials['port'],
                dbname=self.credentials['dbname'],
                user=self.credentials['user'],
                password=self.credentials['password'],
                options='-c statement_timeout=30000'  # 30-second timeout for queries
            )
            print("โœ… Connection successful!")
        except Exception as e:
            logging.error(f"Failed to connect to database: {e}")
            print(f"โŒ Failed to connect to database: {e}")

    def query(self, sql_query):
        """
        Execute a SQL query and return results as a pandas DataFrame.
        """
        if self.conn is None:
            print("No connection established. Please call `connect()` first.")
            return None

        try:
            df = pd.read_sql_query(sql_query, self.conn)  # Run query and store results as DataFrame
            print("โœ… Query executed successfully!")
            return df
        except Exception as e:
            logging.error(f"Failed to execute query: {e}")
            print(f"โŒ Failed to execute query: {e}")
            return None

    def close(self):
        """
        Close the database connection.
        """
        if self.conn:
            self.conn.close()
            print("๐Ÿ”’ Connection closed.")

    def __enter__(self):
        """
        Enable use with 'with' statement for automatic resource management.
        """
        self.connect()
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        """
        Automatically close the connection when exiting 'with' block.
        """
        self.close()

---

### **๐ŸŒŸ How to Use the `PostgresConnector`**

1. **Create a JSON configuration file** (`db_config.json`):
   ```json
   {
       "host": "your_postgres_host",
       "port": "5432",
       "dbname": "your_database_name",
       "user": "your_username",
       "password": "your_password"
   }
  1. Run your Python script:
    if __name__ == "__main__":
        with PostgresConnector('db_config.json') as db:
            query = "SELECT * FROM your_table_name LIMIT 10;"  # Example SQL query
            data = db.query(query)  # Run the query and get a DataFrame
            if data is not None:
                print(data)  # Print the DataFrame for verification
    

๐Ÿ” Key Features

  • Error Logging: All connection and query issues are logged into db_connector.log for debugging.
  • Timeout Option: Prevents queries from hanging indefinitely by setting a 30-second timeout.
  • Resource Management: The with statement ensures the database connection is automatically closed after the query execution.
  • pandas Integration: Results are directly returned as a DataFrame for further analysis.

๐Ÿš€ Benefits of Using This Approach

  • Secure and Flexible: No hardcoded credentialsโ€”everything is stored in a separate configuration file.
  • Clean Code: Automatic resource management with __enter__ and __exit__.
  • Scalable: Easily reusable for multiple projects.

๐Ÿ”— Need help with database queries or optimizations? Let me know your questions or drop a comment below! ๐Ÿ˜Š

Updated: