Appendix B: Python Environment Setup

This appendix walks you through setting up a complete Python development environment for the code exercises, simulations, and data analysis tasks throughout this textbook. By the end, you will have Python 3.10+, a dedicated virtual environment, all required packages, and Jupyter notebooks ready for interactive work.


B.1 Python Installation

The textbook code requires Python 3.10 or later. Earlier versions lack required syntax features (structural pattern matching, updated type hints) and may have incompatible library versions.

Windows

  1. Download the latest Python installer from python.org/downloads.
  2. Run the installer. Check "Add python.exe to PATH" on the first screen before clicking "Install Now."
  3. Verify the installation:
python --version
# Expected: Python 3.10.x or later

pip --version
# Expected: pip 23.x or later

Troubleshooting: If python opens the Microsoft Store or is not recognized, the PATH was not configured. Search Windows Settings for "Manage app execution aliases" and disable the Python app installers. Then re-run the Python installer and ensure "Add to PATH" is checked.

macOS

The system Python on macOS is typically outdated. Install a current version with Homebrew:

# Install Homebrew if not already present
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"

# Install Python
brew install python@3.12

# Verify
python3 --version
pip3 --version

Note

On macOS, use python3 and pip3 rather than python and pip to avoid invoking the legacy system Python.

Linux (Ubuntu/Debian)

sudo apt update
sudo apt install python3.12 python3.12-venv python3-pip

# Verify
python3 --version
pip3 --version

For other distributions, use the system package manager (dnf on Fedora, pacman on Arch) or build from source using pyenv:

# Using pyenv (any Linux distribution)
curl https://pyenv.run | bash
# Follow the shell configuration instructions printed by the installer
pyenv install 3.12.2
pyenv global 3.12.2

B.2 Virtual Environment Setup

A virtual environment isolates the textbook's package dependencies from your system Python and other projects. This prevents version conflicts and keeps your global Python installation clean.

Creating the Environment

Navigate to a directory where you want to store the textbook code, then create and activate a virtual environment:

# Create a project directory
mkdir blockchain-textbook
cd blockchain-textbook

# Create the virtual environment
python3 -m venv .venv

Activating the Environment

You must activate the environment each time you open a new terminal session:

Platform Shell Command
Windows Command Prompt .venv\Scripts\activate.bat
Windows PowerShell .venv\Scripts\Activate.ps1
Windows Git Bash source .venv/Scripts/activate
macOS / Linux bash/zsh source .venv/bin/activate

When active, your prompt will show (.venv) as a prefix:

(.venv) $ python --version
Python 3.12.2

Deactivating

deactivate

Best Practice: Never install textbook packages globally with pip install outside a virtual environment. If you see WARNING: Running pip as the 'root' user, stop and activate your virtual environment first.


B.3 Required Packages

Core Installation

With the virtual environment activated, install all required packages:

pip install --upgrade pip setuptools wheel

pip install \
    web3==7.* \
    eth-abi==5.* \
    eth-account==0.13.* \
    ecdsa==0.19.* \
    pycryptodome==3.20.* \
    requests==2.32.* \
    pandas==2.2.* \
    matplotlib==3.9.* \
    plotly==5.24.* \
    numpy==1.26.* \
    jupyter==1.0.* \
    notebook==7.* \
    python-dotenv==1.0.* \
    tqdm==4.66.*

Package Reference

The following table describes each package and the chapters where it is used:

Package Purpose Chapters
hashlib SHA-256, Keccak-256 hashing (standard library) 2, 3, 5, 35
ecdsa Elliptic curve key generation and signatures 3, 7
pycryptodome AES encryption, advanced cryptographic primitives 3, 18
web3 (web3.py) Ethereum interaction: transactions, contracts, events 11, 13, 14, 19, 20, 22, 33, 35
eth-abi ABI encoding/decoding for Ethereum contracts 13, 14, 35
eth-account Ethereum account management and signing 11, 13, 35
requests HTTP requests for RPC and API calls 6, 33, 35
pandas Data analysis and tabular data manipulation 27, 33, 34, 35
matplotlib Static charts and visualizations 5, 8, 27, 33, 34
plotly Interactive charts and dashboards 27, 33, 34
numpy Numerical computing and array operations 5, 18, 27, 34
jupyter Interactive notebook environment All code chapters
python-dotenv Load environment variables from .env files 13, 33, 35
tqdm Progress bars for long-running operations 5, 35

Note

hashlib and secrets are part of Python's standard library and do not require installation.

Freezing Dependencies

After installation, save the exact versions for reproducibility:

pip freeze > requirements.txt

To recreate the environment later or on a different machine:

pip install -r requirements.txt

B.4 Jupyter Notebook Setup

Jupyter notebooks provide an interactive environment for running code cells, viewing output, and experimenting with blockchain concepts. Many textbook exercises are designed for notebook use.

Launching Jupyter

# From within your activated virtual environment
jupyter notebook

This opens a browser window at http://localhost:8888. Navigate to your project directory and create a new Python 3 notebook.

JupyterLab Alternative

JupyterLab provides a more modern interface:

pip install jupyterlab
jupyter lab

Verifying the Kernel

Ensure the notebook is using your virtual environment's Python:

# Run this in the first cell of any notebook
import sys
print(sys.executable)
# Should print a path inside your .venv directory

If the path points to the system Python instead, register the virtual environment as a Jupyter kernel:

pip install ipykernel
python -m ipykernel install --user --name=blockchain --display-name="Python (Blockchain)"

Then select "Python (Blockchain)" from the kernel menu in Jupyter.

Add this cell at the top of your notebooks for consistent output:

# Standard imports and display settings
import warnings
warnings.filterwarnings('ignore')

# Auto-reload modules when changed
%load_ext autoreload
%autoreload 2

# Inline plots
%matplotlib inline

import matplotlib.pyplot as plt
plt.rcParams['figure.figsize'] = (10, 6)
plt.rcParams['figure.dpi'] = 100

B.5 Environment Variables and API Keys

Several chapters require API keys for blockchain data providers. Store these securely in a .env file (never commit this to version control):

# Create .env file in your project root
touch .env

Add your keys:

# .env
INFURA_API_KEY=your_infura_project_id
ALCHEMY_API_KEY=your_alchemy_api_key
ETHERSCAN_API_KEY=your_etherscan_api_key

Load them in Python:

from dotenv import load_dotenv
import os

load_dotenv()

infura_key = os.getenv("INFURA_API_KEY")
alchemy_key = os.getenv("ALCHEMY_API_KEY")

Obtaining Free API Keys

Provider URL Free Tier
Infura infura.io 100K requests/day
Alchemy alchemy.com 300M compute units/month
Etherscan etherscan.io/apis 5 calls/second

Security Warning: Add .env to your .gitignore immediately. Never hardcode API keys or private keys in source files.


B.6 Verification Script

Run this script to confirm everything is installed correctly. Save it as verify_setup.py:

#!/usr/bin/env python3
"""
Blockchain Textbook Environment Verification Script
Run: python verify_setup.py
"""

import sys

def check_python_version():
    v = sys.version_info
    if v.major == 3 and v.minor >= 10:
        print(f"  [PASS] Python {v.major}.{v.minor}.{v.micro}")
        return True
    else:
        print(f"  [FAIL] Python {v.major}.{v.minor}.{v.micro} — need 3.10+")
        return False

def check_package(name, import_name=None):
    import_name = import_name or name
    try:
        mod = __import__(import_name)
        version = getattr(mod, '__version__', 'installed')
        print(f"  [PASS] {name} ({version})")
        return True
    except ImportError:
        print(f"  [FAIL] {name} — not installed")
        return False

def check_hashlib():
    import hashlib
    test = hashlib.sha256(b"blockchain").hexdigest()
    expected = "625da44e4eaf58d61cf048d168aa6f5e492dea166d8bb54f06c3b1f4a001be23"
    if test == expected:
        print("  [PASS] hashlib SHA-256 — correct output")
        return True
    else:
        print("  [FAIL] hashlib SHA-256 — unexpected output")
        return False

def check_web3_provider():
    try:
        from web3 import Web3
        w3 = Web3()
        addr = w3.to_checksum_address("0x" + "0" * 40)
        print(f"  [PASS] web3.py — address utilities working ({addr[:10]}...)")
        return True
    except Exception as e:
        print(f"  [FAIL] web3.py — {e}")
        return False

def check_ecdsa():
    try:
        from ecdsa import SigningKey, SECP256k1
        sk = SigningKey.generate(curve=SECP256k1)
        vk = sk.get_verifying_key()
        sig = sk.sign(b"test message")
        assert vk.verify(sig, b"test message")
        print("  [PASS] ecdsa — key generation and signing working")
        return True
    except Exception as e:
        print(f"  [FAIL] ecdsa — {e}")
        return False

def check_jupyter():
    try:
        import notebook
        version = notebook.__version__
        print(f"  [PASS] Jupyter Notebook ({version})")
        return True
    except ImportError:
        print("  [FAIL] Jupyter Notebook — not installed")
        return False

def main():
    print("\n=== Blockchain Textbook Environment Check ===\n")

    results = []

    print("[1/7] Python version")
    results.append(check_python_version())

    print("\n[2/7] Core packages")
    for pkg, imp in [
        ("web3", "web3"),
        ("eth-abi", "eth_abi"),
        ("eth-account", "eth_account"),
        ("ecdsa", "ecdsa"),
        ("pycryptodome", "Crypto"),
        ("requests", "requests"),
    ]:
        results.append(check_package(pkg, imp))

    print("\n[3/7] Data & visualization packages")
    for pkg in ["pandas", "numpy", "matplotlib", "plotly"]:
        results.append(check_package(pkg))

    print("\n[4/7] Utility packages")
    for pkg, imp in [("python-dotenv", "dotenv"), ("tqdm", "tqdm")]:
        results.append(check_package(pkg, imp))

    print("\n[5/7] Hashlib SHA-256")
    results.append(check_hashlib())

    print("\n[6/7] Web3 provider utilities")
    results.append(check_web3_provider())

    print("\n[7/7] ECDSA cryptography")
    results.append(check_ecdsa())

    passed = sum(results)
    total = len(results)
    print(f"\n{'='*45}")
    print(f"Results: {passed}/{total} checks passed")

    if passed == total:
        print("Your environment is ready. Start with Chapter 1!\n")
    else:
        print("Some checks failed. Review the [FAIL] items above.\n")
        sys.exit(1)

if __name__ == "__main__":
    main()

Run it:

python verify_setup.py

Expected output when everything is configured correctly:

=== Blockchain Textbook Environment Check ===

[1/7] Python version
  [PASS] Python 3.12.2

[2/7] Core packages
  [PASS] web3 (7.6.0)
  [PASS] eth-abi (5.1.0)
  ...

Results: 16/16 checks passed
Your environment is ready. Start with Chapter 1!

B.7 Troubleshooting Common Issues

"pip: command not found"

Python was installed without pip, or pip is not on the PATH.

# Re-install pip
python3 -m ensurepip --upgrade

"Microsoft Visual C++ 14.0 or greater is required" (Windows)

Some packages (notably pycryptodome) require C compilation tools on Windows.

  1. Install Microsoft C++ Build Tools.
  2. In the installer, select "Desktop development with C++."
  3. Restart your terminal and retry pip install.

Alternatively, install the pre-built binary wheel:

pip install pycryptodome --only-binary=:all:

"error: externally-managed-environment" (Linux)

Modern Linux distributions (Debian 12+, Ubuntu 23.04+) prevent global pip installs to protect system packages. This is expected and correct. Always use a virtual environment:

python3 -m venv .venv
source .venv/bin/activate
pip install <package>

web3.py Connection Errors

If you see ConnectionError when connecting to an Ethereum node:

  1. Verify your API key is correct in .env.
  2. Check the provider URL format:
from web3 import Web3

# Infura
w3 = Web3(Web3.HTTPProvider(f"https://mainnet.infura.io/v3/{infura_key}"))

# Alchemy
w3 = Web3(Web3.HTTPProvider(f"https://eth-mainnet.g.alchemy.com/v2/{alchemy_key}"))

# Local node (Ganache, Hardhat)
w3 = Web3(Web3.HTTPProvider("http://127.0.0.1:8545"))

print(w3.is_connected())  # Should print True
  1. For chapters using only local simulations (no live network), you do not need an API key.

Jupyter Kernel Dies on Import

If the Jupyter kernel crashes when importing large packages, increase the memory available:

# Set environment variable before launching
export JUPYTER_MEMORY_LIMIT=4096  # MB
jupyter notebook

On Windows (PowerShell):

$env:JUPYTER_MEMORY_LIMIT = "4096"
jupyter notebook

M1/M2/M3 Mac (Apple Silicon) Issues

Some packages may not have pre-built ARM wheels. If installation fails:

# Ensure you're using a native ARM Python (not Rosetta)
python3 -c "import platform; print(platform.machine())"
# Should print: arm64

# If a package fails to build, try:
pip install --no-cache-dir <package>

Organize your textbook code as follows:

blockchain-textbook/
    .venv/                  # Virtual environment (do not commit)
    .env                    # API keys (do not commit)
    .gitignore
    requirements.txt        # Frozen dependencies
    verify_setup.py         # Verification script
    notebooks/
        ch02_hashing.ipynb
        ch03_keys.ipynb
        ch05_mining_sim.ipynb
        ...
    scripts/
        mining_simulator.py
        merkle_tree.py
        ...
    data/
        blocks.csv
        transactions.json
        ...

Create a .gitignore to exclude sensitive and generated files:

.venv/
.env
__pycache__/
*.pyc
.ipynb_checkpoints/
*.egg-info/
dist/
build/

You are now ready to run every Python exercise in this textbook. If you encounter issues not covered here, consult the package documentation linked in the further-reading sections of each chapter, or post a question on the textbook's community forum.