Everyone talks about JavaScript for web3 development, but here's the thing - Python works just fine. Actually, it works really well, especially when you've got libraries like web3.py doing the heavy lifting.
I spent way too much time at the beginning trying to figure out how to connect my Python backend to blockchain networks. Turns out, once you get past the initial setup hurdles, it's surprisingly straightforward.
If you’re a Python dev curious about crypto, or working on a backend that needs to talk to a blockchain, this guide is for you.
Web3.py
Imagine your blockchain network as a complex smart home, filled with devices like smart lights, thermostats, and security cameras. Each device understands a unique, complicated set of signals. Controlling them manually would be chaos.
Now imagine having one remote that works with everything. You press "lights on" and it figures out the exact signals to send. That's basically what web3.py does for blockchain interaction.
Without it, you'd be manually crafting JSON-RPC requests (which I definitely tried at first - not fun). With it, you write normal Python code and let the library handle all that network protocol stuff behind the scenes.
What Actually Is web3.py?
It's a Python library that translates your regular Python commands into the JSON-RPC calls that Ethereum nodes understand. Remember those RPC requests we talked about before? This library handles all of that for you.
So instead of manually constructing this:
{"jsonrpc": "2.0", "method": "eth_blockNumber", "params": [], "id": 1}
You just write:
w3.eth.block_number
Much better, right?
With web3.py you can query data, send transactions, and interact with smart contracts, all with clean Python code.
Getting Started: Installation and Setup
Let's get this thing working. First, the usual Python project setup:
mkdir my-web3-app
cd my-web3-app
python3 -m venv venv
source venv/bin/activate # Windows: venv\Scripts\activate
pip install web3 python-dotenv
Connecting to an Ethereum Node (Your RPC Provider)
Here's where I got stuck initially. To talk to any blockchain, you need to connect to a node. These are computers running blockchain software that maintain copies of the ledger.
You've got two main options:
*1: Use a service like Infura or Alchemy *
These companies run blockchain nodes for you. Sign up, get an API key, and you're connected to the real Ethereum network. Great for production
How to get one: Sign up for a free account at Infura.io](https://www.infura.io/) or Alchemy.com. Create a new project for the Ethereum Mainnet or a testnet (e.g., Sepolia) and copy your HTTP endpoint URL.
*2: Run your own local blockchain *
When I first started, I didn’t know this was a thing. I was constantly hunting for testnet faucets and hitting request limits. Then I discovered Ganache.
It spins up a personal Ethereum blockchain on your machine. Perfect for local testing, and it gives you free ETH (fake, of course).
For this tutorial, we're going with Option 2 using Ganache. Trust me on this one - it'll save you so much hassle while learning.
Setting Up Ganache
* Download Ganache Desktop (easiest for beginners).
* Install it and launch. It will automatically start a local blockchain with pre-funded accounts and display its RPC server address (usually http://127.0.0.1:7545
).
If you're having trouble setting it up, check this put
If you use local you can get your url here in Gananche once you've installed it.
Keeping Your Secrets Safe
Before we write any code, let's set up environment variables. Create a .env file in your project folder:
# .env
RPC_URL="http://127.0.0.1:7545"
# Later, when you want to use Infura:
# RPC_URL="https://mainnet.infura.io/v3/YOUR_PROJECT_ID"
And add this to a .gitignore file so you don't accidentally commit your API keys:
.env
venv/
Your First Connection
Now for the actual Python code. Create app.py:
# app.py
import os
from web3 import Web3, HTTPProvider
from dotenv import load_dotenv
# Load environment variables from .env file
load_dotenv()
# Get the RPC URL from environment variables
RPC_URL = os.getenv("RPC_URL")
# Ensure the RPC_URL is set
if not RPC_URL:
raise ValueError("RPC_URL not found in .env file. Please set it (e.g., GANACHE_URL or INFURA_URL).")
try:
# Initialize Web3.py with an HTTP provider
w3 = Web3(HTTPProvider(RPC_URL))
# Test the connection to the Ethereum node
if w3.is_connected():
print(f"✅ Successfully connected to Ethereum node at {RPC_URL}")
else:
print(f"❌ Failed to connect to Ethereum node at {RPC_URL}")
# Exit if connection fails, as subsequent operations will also fail
exit()
except Exception as e:
print(f"An error occurred during connection: {e}")
exit()
Run it with python app.py. If Ganache is running, you should see the success message.
If you've set up Ganache and it's running, you should see ✅ Successfully connected...
. If you use Infura, you'll see a similar message.
Actually Reading From the Blockchain
Now comes the fun part. Let's ask the blockchain some questions:
# app.py (continued from above)
# --- Your First Blockchain Reads ---
print("\n--- Basic Blockchain Data ---")
# 1. Get the latest block number
# This is equivalent to the eth_blockNumber RPC call
latest_block_number = w3.eth.block_number
print(f"📈 Latest Block Number: {latest_block_number}")
# 2. Get the current gas price
# Gas price is returned in Wei (the smallest unit of Ether)
gas_price_wei = w3.eth.gas_price
print(f"⛽ Current Gas Price (Wei): {gas_price_wei}")
# Wei is tiny! Let's convert it to more readable units.
# 1 Ether = 10^18 Wei
# 1 Gwei = 10^9 Wei
print(f"⛽ Current Gas Price (Gwei): {w3.from_wei(gas_price_wei, 'gwei')} Gwei")
print(f"⛽ Current Gas Price (Ether): {w3.from_wei(gas_price_wei, 'ether')} ETH")
# 3. Get an account's Ether balance
# For Ganache, you can use one of the pre-funded accounts.
# If using Infura, pick any public Ethereum address.
if "ganache" in RPC_URL.lower():
# Get the first account Ganache provides
account_to_check = w3.eth.accounts[0]
else:
# Example public address (Vitalik Buterin's ENS primary address on Mainnet)
account_to_check = "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045"
balance_wei = w3.eth.get_balance(account_to_check)
print(f"\n💰 Balance of {account_to_check} (Wei): {balance_wei}")
print(f"💰 Balance of {account_to_check} (Ether): {w3.from_wei(balance_wei, 'ether')} ETH")
# 4. Get details of a specific block (e.g., the latest block)
block_info = w3.eth.get_block(latest_block_number)
print(f"\n📄 Details for Block {latest_block_number}:")
print(f" Hash: {block_info['hash'].hex()}") # Convert bytes to hex string for display
print(f" Miner: {block_info['miner']}")
print(f" Timestamp: {block_info['timestamp']} (Unix)")
print(f" Number of Transactions: {len(block_info['transactions'])}")
print("\n--- End of Basic Reads ---")
Run python app.py
again, and you'll see all this blockchain data printed to your console!
You probably noticed all those w3.from_wei() calls. Here's the deal: Ethereum uses really tiny units internally to avoid floating-point math errors.
- 1 ETH = 1,000,000,000,000,000,000 wei (that's 18 zeros)
- 1 ETH = 1,000,000,000 gwei (9 zeros)
So when the blockchain returns 20000000000, that's actually 20 gwei, not 20 ETH. The conversion functions save you from doing that math yourself.
What You Just Accomplished
Pretty cool, right? You just:
Connected Python to a blockchain network
- Queried live blockchain data
- Handled the weird unit conversions automatically
- Did it all with clean, readable Python code
No manual JSON-RPC construction, no hex encoding/decoding headaches, no network protocol debugging. Just Python talking to blockchain.
What's Coming Next
Next time, we're going to deploy and interact with smart contracts. That's where things get really interesting - calling functions, sending transactions, handling events.
But first, play around with this code.
Quick troubleshooting: If Ganache won't start, check if port 7545 is already in use. If you're getting connection errors, make sure your .env file is in the right directory and the RPC_URL is uncommented.
Top comments (0)