Data Storage in Python
A complete beginner's guide to saving and retrieving data in Python: text and binary files, CSV, JSON, pickle, SQLite, MySQL and PostgreSQL, and cloud storage. Every method with working code and clear guidance on when to use it.
Whether you are building a small script or a large-scale application, at some point you will need to store and retrieve data. Data storage in Python is one of the most practical skills to master, and the good news is that Python offers many ways to do it, from simple text files all the way to databases and cloud-based solutions.
This guide walks you through every common method for storing data in Python, with a working example for each and, just as importantly, clear advice on which method to choose for your project. By the end you will know exactly when to reach for a JSON file, when a database makes more sense, and when to store objects directly with pickle.
The methods covered in this guide are:
- Text and binary files
- CSV files for tabular data
- JSON for structured data
- Pickle for Python object serialization
- SQLite, Python's built-in database
- External databases (MySQL and PostgreSQL)
- Cloud and file storage APIs (overview)
Storing Data in Text Files
Storing data in a .txt file is the simplest form of data storage in Python. It is perfect for logs, configuration settings, notes, or any simple data that does not need a rigid structure. Python handles text files natively, so no imports are required.
Write to a text file
You open the file in write mode ("w") and use write() to add content. The with statement is the recommended approach because it automatically closes the file for you, even if an error occurs.
with open("data.txt", "w") as file: file.write("Hello, World!\n") file.write("Welcome to Python.")
Read from a text file
Open the file in read mode ("r") and use read() to pull the whole contents into a string.
with open("data.txt", "r") as file: content = file.read() print(content)
Understanding file modes
The second argument to open() is the mode, and choosing the right one matters. Using "w" when you meant "a" will silently erase your file.
| Mode | Meaning | Behaviour |
|---|---|---|
"r" | Read | Opens for reading. Errors if the file does not exist |
"w" | Write | Creates a new file, or overwrites an existing one completely |
"a" | Append | Adds to the end of the file without erasing existing content |
"r+" | Read and write | Opens for both reading and writing |
"b" | Binary | Added to another mode (such as "rb") for non-text files like images |
"w" mode erases everything already in it the moment you open it. If you want to add to a file rather than replace it, use append mode "a" instead.
Storing Data in CSV Files
CSV (Comma-Separated Values) is the ideal format for tabular data: anything that fits neatly into rows and columns, such as spreadsheets, logs, exports and reports. CSV files open directly in Excel and Google Sheets, which makes them a favourite for sharing data with non-programmers. Python includes a built-in csv module, so no installation is needed.
Writing to a CSV file
Each inner list becomes one row. The newline="" argument prevents blank lines from appearing between rows on Windows, a very common beginner gotcha.
import csv data = [ ["Name", "Age"], ["Alice", 25], ["Bob", 30] ] with open("data.csv", "w", newline="") as file: writer = csv.writer(file) writer.writerows(data)
Reading from a CSV file
The reader gives you back each row as a list of strings, which you can loop over.
with open("data.csv", "r") as file: reader = csv.reader(file) for row in reader: print(row)
Working with columns by name
When your CSV has a header row, DictReader lets you access each value by its column name instead of a numeric index, which makes your code far easier to read.
import csv with open("data.csv", "r") as file: reader = csv.DictReader(file) for row in reader: print(row["Name"], "is", row["Age"])
Storing Data in JSON Files
JSON (JavaScript Object Notation) is excellent for hierarchical or structured data, such as dictionaries, nested lists, or data returned from web APIs. It maps almost perfectly onto Python's dictionaries and lists, and it is readable by nearly every programming language, which is why it has become the standard format for exchanging data on the web. Python's built-in json module handles it all.
Writing JSON
json.dump() converts a Python dictionary into JSON text and writes it to a file. Adding indent=4 makes the saved file neatly formatted and human-readable.
import json data = {"name": "Alice", "age": 25, "skills": ["Python", "SQL"]} with open("data.json", "w") as file: json.dump(data, file, indent=4)
Reading JSON
json.load() reads the file and converts the JSON back into a Python dictionary, which you can then access by key exactly like any other dictionary.
import json with open("data.json", "r") as file: data = json.load(file) print(data["name"]) print(data["skills"])
json.dump() to write straight to a file, and json.dumps() (with an s) to turn data into a JSON string you can print, log, or send over a network. The same pattern applies to load() and loads() when reading.
Pickle: Store Python Objects Directly
Sometimes you want to save a Python object exactly as it is, a list, a dictionary, or even a custom class instance, and load it back later without rebuilding it. The pickle module does this by serializing the object into a binary format. Serialization simply means converting an object into a stream of bytes that can be stored and later reconstructed.
Pickle example
Note the binary modes: "wb" for writing bytes and "rb" for reading bytes. Pickle files are not text, so they must be opened in binary mode.
import pickle my_data = {"username": "admin", "scores": [10, 20, 30]} # Save (serialize) the object with open("data.pkl", "wb") as file: pickle.dump(my_data, file) # Load (deserialize) it back with open("data.pkl", "rb") as file: loaded_data = pickle.load(file) print(loaded_data)
Pickle vs JSON
The two are easy to confuse, so here is the clear difference:
| Pickle | JSON | |
|---|---|---|
| Format | Binary, not human-readable | Text, human-readable |
| Language support | Python only | Almost every language |
| Can store | Almost any Python object, including classes | Basic types: dicts, lists, strings, numbers |
| Security | Unsafe with untrusted data | Safe to load |
Storing Data in SQLite
Once your data grows or you need to search, filter and sort it efficiently, files start to feel limiting. This is where a database comes in. SQLite is a lightweight, file-based database built right into Python, no server or installation required. The entire database lives in a single file, which makes it perfect for small to medium applications, prototypes, and mobile apps.
A complete SQLite example
This example connects to a database (creating it if it does not exist), creates a table, inserts a row, and reads it back.
import sqlite3 # Connect to a database, or create one if it does not exist conn = sqlite3.connect("mydata.db") cursor = conn.cursor() # Create a table cursor.execute("CREATE TABLE IF NOT EXISTS users (name TEXT, age INTEGER)") # Insert data cursor.execute("INSERT INTO users VALUES ('Alice', 25)") conn.commit() # Read data cursor.execute("SELECT * FROM users") print(cursor.fetchall()) conn.close()
The three steps that trip people up
- commit(): changes such as inserts are not saved until you call
conn.commit(). Forget this and your data vanishes when the program ends. - close(): always close the connection when you are done to release the file.
- fetchall(): a
SELECTquery does not return rows directly. You retrieve them withfetchall()for all rows orfetchone()for a single row.
Use placeholders to stay safe
Never build SQL queries by joining strings with user input, as it opens you up to SQL injection attacks. Use ? placeholders and pass the values separately.
name = "Bob" age = 30 # Safe: values are passed separately as a tuple cursor.execute("INSERT INTO users VALUES (?, ?)", (name, age)) conn.commit()
External Databases: MySQL and PostgreSQL
For larger applications, especially multi-user web apps where many people read and write data at the same time, you will move up to a full database server such as MySQL or PostgreSQL. These run as a separate service that your Python program connects to over a network, and they handle far larger volumes of data reliably.
Installing the connectors
Each database has its own Python library, installed with pip:
# For MySQL pip install mysql-connector-python # For PostgreSQL pip install psycopg2
Example: connecting to MySQL
The pattern is very similar to SQLite. The main difference is the connection step, where you provide the host, username, password and database name.
import mysql.connector conn = mysql.connector.connect( host="localhost", user="root", password="yourpassword", database="mydb" ) cursor = conn.cursor() cursor.execute("SELECT * FROM users") print(cursor.fetchall()) conn.close()
Cloud Storage (Advanced)
When your data needs to be accessible from anywhere, backed up automatically, or shared across web and mobile apps, cloud storage is the answer. Python has mature libraries for every major cloud provider. These all require authentication with the service, so they are a step up in complexity, but the storage concepts remain the same.
| Service | Python library | Typical use |
|---|---|---|
| Google Drive | pydrive or gdown | File backups and sharing |
| Firebase | firebase-admin | Real-time app data and mobile back-ends |
| AWS S3 | boto3 | Scalable file and object storage |
| Google Sheets | gspread | Reading and writing spreadsheet data |
These are well suited to web applications, automated backups, and mobile integrations. Because each provider handles authentication differently, always follow the official documentation for the library you choose.
Summary: Best Python Data Storage Methods
Here is every method side by side, so you can compare them at a glance.
| Format | Best for | Pros | Limitations |
|---|---|---|---|
.txt | Simple data | Easy to read and write | No structure |
.csv | Tables | Human-readable, opens in Excel | Only rows and columns |
.json | Hierarchical data | Structured, widely used | No support for functions or objects |
pickle | Python objects | Very flexible | Not human-readable, insecure with untrusted data |
| SQLite | Small databases | Built-in, fast, real queries | Local use only |
| MySQL / PostgreSQL | Scalable apps | Powerful and reliable | Needs setup and a server |
| Cloud (S3, Firebase) | Online apps | Accessible anywhere | Complex integration |
Final Thoughts: How to Choose
There is no single best way to store data in Python. The right choice depends on your project, and it comes down to four questions:
- What type of data are you storing? Plain notes suit text files, tables suit CSV, nested data suits JSON, and Python objects suit pickle.
- How much data do you have? A handful of records is fine in a file. Thousands of records that need searching call for a database.
- Who or what will access the data? If only your own Python program reads it, pickle is convenient. If other languages or people need it, use JSON, CSV or a database.
- Do you need local or remote access? Local projects can use files or SQLite. Remote and multi-user projects need a database server or cloud storage.
A good rule of thumb for beginners: start simple with files, move to JSON when your data becomes structured, and step up to SQLite the moment you find yourself wanting to search or filter your data. Master these and you will have the right tool for almost any project.
