BLOG POSTS
    MangoHost Blog / Creating Diagrams in Python with Diagram-as-Code Tools
Creating Diagrams in Python with Diagram-as-Code Tools

Creating Diagrams in Python with Diagram-as-Code Tools

Creating diagrams for system architecture, network topology, or application workflows has traditionally been a tedious task involving manual drawing tools and constant updates. Diagram-as-code tools revolutionize this process by allowing developers to generate professional diagrams using simple Python scripts, making documentation more maintainable, version-controllable, and automatically updatable. This guide will walk you through the most popular Python diagram-as-code libraries, show you how to create various types of technical diagrams, and help you choose the right tool for your specific needs.

How Diagram-as-Code Tools Work

Diagram-as-code tools transform textual descriptions or programmatic definitions into visual representations. Instead of dragging and dropping icons in a GUI application, you write code that describes the components and their relationships. The tool then renders this into formats like PNG, SVG, or PDF.

The core concept revolves around three main approaches:

  • Declarative syntax: Tools like Diagrams use Python objects to represent infrastructure components
  • Domain-specific languages: Tools like PlantUML use specialized markup languages
  • Graph-based definitions: Libraries like Graphviz use node and edge relationships

Python-based solutions typically leverage rendering engines like Graphviz, Cairo, or custom SVG generators to produce the final output. The major advantage is that your diagrams become part of your codebase, enabling version control, automated generation, and integration with CI/CD pipelines.

Popular Python Diagram-as-Code Libraries

Library Best For Output Formats Learning Curve GitHub Stars
Diagrams Cloud architecture diagrams PNG, JPG, SVG, PDF Low 35k+
PlantUML (Python wrapper) UML diagrams, sequence diagrams PNG, SVG, PDF, LaTeX Medium Multiple implementations
Graphviz (Python bindings) Generic graphs, flowcharts PNG, SVG, PDF, PostScript Medium-High 1.5k+
Mermaid (Python integration) Flowcharts, gantt charts PNG, SVG, PDF Low-Medium 65k+ (JS project)

Step-by-Step Implementation Guide

Setting Up the Diagrams Library

The Diagrams library is the most popular choice for infrastructure diagrams. Here’s how to get started:

# Install required dependencies
pip install diagrams

# On Ubuntu/Debian, you might need Graphviz
sudo apt-get install graphviz

# On macOS
brew install graphviz

# On Windows, download from https://graphviz.org/download/

Creating Your First Architecture Diagram

from diagrams import Diagram
from diagrams.aws.compute import EC2
from diagrams.aws.database import RDS
from diagrams.aws.network import ELB
from diagrams.aws.storage import S3

with Diagram("Web Service Architecture", show=False, direction="TB"):
    lb = ELB("Load Balancer")
    
    with Cluster("Web Servers"):
        web_servers = [EC2("web1"), EC2("web2"), EC2("web3")]
    
    db = RDS("Database")
    storage = S3("Static Files")
    
    lb >> web_servers >> db
    web_servers >> storage

This code generates a clean architectural diagram showing a typical web application setup. The show=False parameter prevents the diagram from opening automatically, and direction="TB" sets a top-to-bottom layout.

Advanced Diagrams with Custom Styling

from diagrams import Diagram, Cluster, Edge
from diagrams.aws.compute import ECS, Lambda
from diagrams.aws.database import Dynamodb
from diagrams.aws.integration import SQS
from diagrams.aws.network import APIGateway

graph_attr = {
    "fontsize": "16",
    "bgcolor": "white"
}

with Diagram("Microservices Architecture", 
             show=False, 
             graph_attr=graph_attr,
             filename="microservices"):
    
    api = APIGateway("API Gateway")
    
    with Cluster("Processing"):
        processors = [
            ECS("User Service"),
            ECS("Order Service"),
            Lambda("Payment Function")
        ]
    
    queue = SQS("Message Queue")
    db = Dynamodb("NoSQL Database")
    
    api >> processors
    processors >> Edge(color="red", style="dashed") >> queue
    processors >> db

Working with Different Diagram Types

Network Topology Diagrams

from diagrams import Diagram, Cluster
from diagrams.generic.network import Router, Switch, Firewall
from diagrams.generic.compute import Rack

with Diagram("Network Topology", show=False):
    internet = Router("Internet")
    
    with Cluster("DMZ"):
        firewall = Firewall("Firewall")
        
    with Cluster("Internal Network"):
        switch = Switch("Core Switch")
        servers = [Rack("Server Rack 1"), Rack("Server Rack 2")]
    
    internet >> firewall >> switch >> servers

Database Relationship Diagrams

from diagrams import Diagram, Edge
from diagrams.generic.database import SQL

with Diagram("Database Schema", show=False):
    users = SQL("Users")
    orders = SQL("Orders") 
    products = SQL("Products")
    order_items = SQL("Order Items")
    
    users >> Edge(label="1:N") >> orders
    orders >> Edge(label="1:N") >> order_items
    products >> Edge(label="1:N") >> order_items

Using PlantUML with Python

For more complex UML diagrams, PlantUML offers extensive capabilities. You can integrate it with Python using the plantuml package:

pip install plantuml
import plantuml

# Define PlantUML diagram syntax
uml_code = """
@startuml
class User {
    -id: int
    -name: string
    -email: string
    +login()
    +logout()
}

class Order {
    -id: int
    -date: datetime
    -total: decimal
    +calculate_total()
}

User ||--o{ Order
@enduml
"""

# Generate diagram
server = plantuml.PlantUML(url='http://www.plantuml.com/plantuml/img/')
image_data = server.processes(uml_code)

with open('class_diagram.png', 'wb') as f:
    f.write(image_data)

Real-World Use Cases and Examples

CI/CD Pipeline Documentation

Automatically generate pipeline diagrams that stay synchronized with your actual infrastructure:

from diagrams import Diagram, Cluster, Edge
from diagrams.generic.compute import Rack
from diagrams.programming.framework import React
from diagrams.onprem.vcs import Git

with Diagram("CI/CD Pipeline", show=False):
    developer = React("Developer")
    repo = Git("Repository")
    
    with Cluster("CI/CD"):
        build = Rack("Build Server")
        test = Rack("Test Server")
        deploy = Rack("Deploy Server")
    
    with Cluster("Environments"):
        staging = Rack("Staging")
        prod = Rack("Production")
    
    developer >> repo >> build >> test >> deploy
    deploy >> staging >> Edge(label="manual approval") >> prod

Monitoring and Alerting Architecture

from diagrams import Diagram, Cluster
from diagrams.onprem.monitoring import Prometheus, Grafana
from diagrams.onprem.logging import Elasticsearch, Kibana
from diagrams.generic.compute import Rack

with Diagram("Monitoring Stack", show=False):
    with Cluster("Applications"):
        apps = [Rack(f"App {i}") for i in range(1, 4)]
    
    with Cluster("Monitoring"):
        prometheus = Prometheus("Prometheus")
        grafana = Grafana("Grafana")
    
    with Cluster("Logging"):
        elastic = Elasticsearch("Elasticsearch")
        kibana = Kibana("Kibana")
    
    apps >> prometheus >> grafana
    apps >> elastic >> kibana

Best Practices and Common Pitfalls

Best Practices

  • Version control your diagrams: Store diagram code alongside your infrastructure code
  • Use meaningful names: Avoid generic labels like “server1” – use descriptive names like “user-auth-service”
  • Organize with clusters: Group related components to improve readability
  • Consistent styling: Define graph attributes once and reuse them across projects
  • Automate generation: Include diagram generation in your CI/CD pipeline

Common Issues and Solutions

Problem: Graphviz not found error

# Solution: Ensure Graphviz is in your PATH
export PATH="/usr/local/bin:$PATH"  # macOS
# Or on Windows, add C:\Program Files\Graphviz\bin to system PATH

Problem: Overlapping nodes in complex diagrams

# Solution: Use graph attributes to control spacing
graph_attr = {
    "splines": "ortho",
    "nodesep": "1.0",
    "ranksep": "1.0"
}

with Diagram("My Diagram", graph_attr=graph_attr):
    # Your diagram code

Problem: Icons not displaying correctly

# Solution: Verify icon paths and use fallbacks
from diagrams.generic.blank import Blank

# Use generic icons as fallbacks
try:
    from diagrams.custom.myservice import MyService
    service = MyService("Custom Service")
except ImportError:
    service = Blank("Custom Service")

Performance Considerations and Optimization

Large diagrams can take significant time to render. Here are optimization strategies:

Diagram Size Render Time Optimization Strategy
< 20 nodes < 2 seconds No optimization needed
20-50 nodes 2-10 seconds Use clustering, simplify layouts
50+ nodes 10+ seconds Split into multiple diagrams, use subgraphs
# Optimization example: Using subgraphs for large architectures
from diagrams import Diagram, Cluster

def create_service_cluster(name, count):
    """Helper function to create service clusters"""
    return [EC2(f"{name}-{i}") for i in range(count)]

with Diagram("Optimized Large Architecture", show=False):
    with Cluster("Frontend"):
        frontend = create_service_cluster("web", 3)
    
    with Cluster("Backend"):
        backend = create_service_cluster("api", 5)
    
    # Connect clusters instead of individual nodes
    frontend >> backend

Integration with Documentation Systems

Integrate diagram generation with popular documentation tools:

# Makefile for automated documentation
generate-docs:
	python generate_diagrams.py
	mkdocs build
	
# Or with Sphinx
sphinx-build:
	python generate_diagrams.py
	sphinx-build -b html docs docs/_build

For GitHub Actions integration:

# .github/workflows/docs.yml
name: Generate Documentation
on: [push]
jobs:
  docs:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v2
    - name: Setup Python
      uses: actions/setup-python@v2
      with:
        python-version: '3.9'
    - name: Install dependencies
      run: |
        sudo apt-get install graphviz
        pip install diagrams
    - name: Generate diagrams
      run: python scripts/generate_diagrams.py
    - name: Deploy to GitHub Pages
      uses: peaceiris/actions-gh-pages@v3
      with:
        github_token: ${{ secrets.GITHUB_TOKEN }}
        publish_dir: ./docs

The diagram-as-code approach transforms technical documentation from a burden into an integrated part of your development workflow. By treating diagrams as code, you ensure they remain accurate, up-to-date, and maintainable throughout your project’s lifecycle. Start with simple architectures using the Diagrams library, then expand to more complex visualizations as your needs grow.

For comprehensive documentation and examples, check out the official Diagrams documentation and the PlantUML official site.



This article incorporates information and material from various online sources. We acknowledge and appreciate the work of all original authors, publishers, and websites. While every effort has been made to appropriately credit the source material, any unintentional oversight or omission does not constitute a copyright infringement. All trademarks, logos, and images mentioned are the property of their respective owners. If you believe that any content used in this article infringes upon your copyright, please contact us immediately for review and prompt action.

This article is intended for informational and educational purposes only and does not infringe on the rights of the copyright owners. If any copyrighted material has been used without proper credit or in violation of copyright laws, it is unintentional and we will rectify it promptly upon notification. Please note that the republishing, redistribution, or reproduction of part or all of the contents in any form is prohibited without express written permission from the author and website owner. For permissions or further inquiries, please contact us.

Leave a reply

Your email address will not be published. Required fields are marked