Python Database Connectivity: SQLite to BigQuery Without Hardcoding Passwords
Connect Python to SQLite, PostgreSQL, MySQL, Snowflake and BigQuery with SQLAlchemy and pandas read_sql — securely via .env files.
Analysts who can only query inside a UI are bottlenecked. This guide makes your notebook the client — SQLite locally, then Postgres/MySQL/Snowflake/BigQuery with the same pd.read_sql call, all without hardcoding a password.
What is the single pattern you memorise?
One engine string per dialect, one pd.read_sql to read, and secrets from .env via python-dotenv. Every dialect section follows the same three lines so you only swap the string.
How do you stop hardcoding passwords?
Setup:
# !pip install pandas sqlalchemy psycopg2-binary pymysql mysql-connector-python snowflake-connector-python google-cloud-bigquery duckdb pyodbc python-dotenv
import os
from dotenv import load_dotenv
load_dotenv() # reads .env in this folder
# create .env with: DB_PASSWORD=my_secret_password
pwd = os.getenv('DB_PASSWORD') # None if missing — fail loudly
print("Env loaded:", pwd is not None)Add .env to .gitignore. No password ever appears in the committed notebook — a hiring-manager hygiene check.
How do you connect to SQLite (zero setup)?
SQLite is a file; no server needed.
import sqlite3
import pandas as pd
conn = sqlite3.connect('example_local_db.sqlite')
cursor = conn.cursor()
cursor.execute("CREATE TABLE IF NOT EXISTS sales (id INTEGER, amount REAL)")
cursor.execute("INSERT INTO sales VALUES (1, 100.50), (2, 200.00)")
conn.commit()
df = pd.read_sql("SELECT * FROM sales", conn)
print("--- Data from SQLite ---")
print(df)
conn.close()Rendered output: a 2-row DataFrame id | amount with 100.5 / 200.0, proving pd.read_sql works on a DB-API connection identical to engines below.
How do you connect to Postgres, MySQL, Snowflake, and BigQuery?
Same call, different engine string.
from sqlalchemy import create_engine
# PostgreSQL: postgresql+psycopg2://user:pass@host:port/db
DB_USER='your_username'; DB_PASS=os.getenv('POSTGRES_PASS','demo')
DB_HOST='localhost'; DB_PORT='5432'; DB_NAME='analytics_db'
pg_str = f'postgresql+psycopg2://{DB_USER}:{DB_PASS}@{DB_HOST}:{DB_PORT}/{DB_NAME}'
engine_pg = create_engine(pg_str)
# df_pg = pd.read_sql("SELECT * FROM employees LIMIT 10", engine_pg)
# MySQL: mysql+pymysql://user:pass@host:port/db
mysql_str = 'mysql+pymysql://root:password123@localhost:3306/my_database'
# engine_mysql = create_engine(mysql_str)
# df_mysql = pd.read_sql("SELECT * FROM orders", engine_mysql)For Google BigQuery, use the native client that returns a DataFrame directly:
# from google.cloud import bigquery
# client = bigquery.Client()
# query = "SELECT * FROM `project.dataset.table` LIMIT 10"
# df_bq = client.query(query).to_dataframe()
# print(df_bq.head())Write path (all dialects via SQLAlchemy):
# df.to_sql('my_table', engine_pg, if_exists='replace', index=False)
# print("Written to Postgres")| Feature / Criteria |
|---|
Gotcha: Forgetting to Close or Pool the Connection
Creating a new engine per query leaks sockets and hits max connections. Create one engine per notebook session and reuse it for every pd.read_sql. Close raw sqlite3 connections with conn.close(); SQLAlchemy engines pool and do not need manual close per query.
How do you layer this into an analyst stack?
Pull via API per API Masterclass -> normalise to DataFrame -> to_sql into Postgres -> query back with read_sql for Pandas shaping. Keep SQL in the database (filter, join) and Pandas for wrangling that SQL does not do well, per SQL vs NoSQL.
Download the Notebook and Practise
This article is a walkthrough of a runnable Jupyter notebook. Download the original .ipynb and run it locally or on Colab — every code block above appears in order.
Download the Database Connectivity Guide Notebook
Get the complete .ipynb with outputs — runs on any Python 3.10+ environment with pandas, numpy, and the libraries listed in setup.
Download .ipynbContinue your track: Data Analyst Roadmap · Python and Pandas Guide · SQL NULL Handbook · SQL JOIN Fan-Out · Topfolio Practice · Data Analyst vs Engineer
Dataset generators where applicable are in courses/workbooks/generators/ — see citations atop for the exact *.py source for this notebook.
Frequently Asked Questions
Why use SQLAlchemy instead of raw DB drivers?
SQLAlchemy provides a single create_engine string per dialect so pd.read_sql works identically for SQLite, Postgres, MySQL, and Snowflake — you only swap the connection string.
How do you avoid hardcoding passwords in notebooks?
Store secrets in a .env file and load with from dotenv import load_dotenv; os.getenv('DB_PASSWORD'). Never commit .env — add it to .gitignore.
Why does pd.read_sql need a connection or engine?
pandas delegates execution to the DB-API/SQLAlchemy connection; the engine manages pooling and dialect translation so you stay in DataFrame-land.
Which library for BigQuery from Python?
google-cloud-bigquery plus SQLAlchemy or direct client.query(sql).to_dataframe(). Authenticate via service-account JSON and set GOOGLE_APPLICATION_CREDENTIALS.
Frequently Asked Questions
Why use SQLAlchemy instead of raw DB drivers?
SQLAlchemy provides a single create_engine string per dialect so pd.read_sql works identically for SQLite, Postgres, MySQL, and Snowflake — you only swap the connection string.
How do you avoid hardcoding passwords in notebooks?
Store secrets in a .env file and load with from dotenv import load_dotenv; os.getenv('DB_PASSWORD'). Never commit .env — add it to .gitignore.
Why does pd.read_sql need a connection or engine?
pandas delegates execution to the DB-API/SQLAlchemy connection; the engine manages pooling and dialect translation so you stay in DataFrame-land.
Which library for BigQuery from Python?
google-cloud-bigquery plus SQLAlchemy or direct client.query(sql).to_dataframe(). Authenticate via service-account JSON and set GOOGLE_APPLICATION_CREDENTIALS.

Written by
Founder at Topfolio with 6+ years in data & analytics across JPMC, Ultrahuman, and high-growth startups. Sat on hiring panels, reviewed 500+ resumes, and writes practical SQL & data guides.
Related Articles
SQL CTE (WITH Clause): Syntax, Chaining, Recursive CTEs & Real Examples (2026)
Master SQL CTEs (Common Table Expressions) using the WITH clause. Learn exact syntax, execution lifecycle, chaining CTEs, recursive CTEs for org hierarchies, and CTEs vs subqueries vs temp tables.
CREATE TABLE in MySQL: Syntax, Data Types & Constraints Guide
Master CREATE TABLE in MySQL with syntax examples, primary keys, foreign keys, AUTO_INCREMENT, constraints, and InnoDB engine best practices.
DDL SQL Commands: Complete Guide to Data Definition Language
Master DDL SQL commands: CREATE, ALTER, DROP, TRUNCATE, and RENAME with practical syntax, schema constraints, and DDL vs DML comparisons.