In diesem Tutorial erstellen wir einen Finish-to-Finish-Workflow zur kognitiven Komplexitätsanalyse mit Komplexität. Wir beginnen mit der Messung der Komplexität direkt anhand der Rohcodezeichenfolgen und skalieren dann dieselbe Analyse auf einzelne Dateien und ein gesamtes Projektverzeichnis. Unterwegs generieren wir maschinenlesbare Berichte, normalisieren sie in strukturierte DataFrames und visualisieren Komplexitätsverteilungen, um zu verstehen, wie sich die Entscheidungstiefe über Funktionen hinweg ansammelt. Indem wir kognitive Komplexität als messbares technisches Sign behandeln, zeigen wir, wie sie auf natürliche Weise in die alltägliche Python-Entwicklung und Qualitätsprüfungen integriert werden kann. Schauen Sie sich das an VOLLSTÄNDIGE CODES hier.
!pip -q set up complexipy pandas matplotlib
import os
import json
import textwrap
import subprocess
from pathlib import Path
import pandas as pd
import matplotlib.pyplot as plt
from complexipy import code_complexity, file_complexity
print("✅ Put in complexipy and dependencies")
Wir richten die Umgebung ein, indem wir die erforderlichen Bibliotheken installieren und alle für die Analyse und Visualisierung erforderlichen Abhängigkeiten importieren. Wir stellen sicher, dass das Pocket book vollständig eigenständig ist und ohne externe Einrichtung in Google Colab ausgeführt werden kann. Es bildet das Rückgrat der Ausführung für alles, was folgt.
snippet = """
def score_orders(orders):
complete = 0
for o in orders:
if o.get("legitimate"):
if o.get("precedence"):
if o.get("quantity", 0) > 100:
complete += 3
else:
complete += 2
else:
if o.get("quantity", 0) > 100:
complete += 2
else:
complete += 1
else:
complete -= 1
return complete
"""
res = code_complexity(snippet)
print("=== Code string complexity ===")
print("Total complexity:", res.complexity)
print("Features:")
for f in res.capabilities:
print(f" - {f.title}: {f.complexity} (strains {f.line_start}-{f.line_end})")
Wir beginnen mit der Analyse einer rohen Python-Codezeichenfolge, um die kognitive Komplexität auf Funktionsebene zu verstehen. Wir untersuchen direkt, wie verschachtelte Bedingungen und Kontrollflüsse zur Komplexität beitragen. Es hilft uns, das Kernverhalten von complexipy zu validieren, bevor wir es auf echte Dateien skalieren.
root = Path("toy_project")
src = root / "src"
exams = root / "exams"
src.mkdir(dad and mom=True, exist_ok=True)
exams.mkdir(dad and mom=True, exist_ok=True)
(src / "__init__.py").write_text("")
(exams / "__init__.py").write_text("")
(src / "easy.py").write_text(textwrap.dedent("""
def add(a, b):
return a + b
def safe_div(a, b):
if b == 0:
return None
return a / b
""").strip() + "n")
(src / "legacy_adapter.py").write_text(textwrap.dedent("""
def legacy_adapter(x, y):
if x and y:
if x > 0:
if y > 0:
return x + y
else:
return x - y
else:
if y > 0:
return y - x
else:
return -(x + y)
return 0
""").strip() + "n")
(src / "engine.py").write_text(textwrap.dedent("""
def route_event(occasion):
variety = occasion.get("variety")
payload = occasion.get("payload", {})
if variety == "A":
if payload.get("x") and payload.get("y"):
return _handle_a(payload)
return None
elif variety == "B":
if payload.get("flags"):
return _handle_b(payload)
else:
return None
elif variety == "C":
for merchandise in payload.get("gadgets", ()):
if merchandise.get("enabled"):
if merchandise.get("mode") == "quick":
_do_fast(merchandise)
else:
_do_safe(merchandise)
return True
else:
return None
def _handle_a(p):
complete = 0
for v in p.get("vals", ()):
if v > 10:
complete += 2
else:
complete += 1
return complete
def _handle_b(p):
rating = 0
for f in p.get("flags", ()):
if f == "x":
rating += 1
elif f == "y":
rating += 2
else:
rating -= 1
return rating
def _do_fast(merchandise):
return merchandise.get("id")
def _do_safe(merchandise):
if merchandise.get("id") is None:
return None
return merchandise.get("id")
""").strip() + "n")
(exams / "test_engine.py").write_text(textwrap.dedent("""
from src.engine import route_event
def test_route_event_smoke():
assert route_event({"variety": "A", "payload": {"x": 1, "y": 2, "vals": (1, 20)}}) == 3
""").strip() + "n")
print(f"✅ Created venture at: {root.resolve()}")
Wir erstellen programmgesteuert ein kleines, aber realistisches Python-Projekt mit mehreren Modulen und Testdateien. Wir integrieren bewusst unterschiedliche Kontrollflussmuster, um sinnvolle Unterschiede in der Komplexität zu schaffen. Schauen Sie sich das an VOLLSTÄNDIGE CODES hier.
engine_path = src / "engine.py"
file_res = file_complexity(str(engine_path))
print("n=== File complexity (Python API) ===")
print("Path:", file_res.path)
print("File complexity:", file_res.complexity)
for f in file_res.capabilities:
print(f" - {f.title}: {f.complexity} (strains {f.line_start}-{f.line_end})")
MAX_ALLOWED = 8
def run_complexipy_cli(project_dir: Path, max_allowed: int = 8):
cmd = (
"complexipy",
".",
"--max-complexity-allowed", str(max_allowed),
"--output-json",
"--output-csv",
)
proc = subprocess.run(cmd, cwd=str(project_dir), capture_output=True, textual content=True)
preferred_csv = project_dir / "complexipy.csv"
preferred_json = project_dir / "complexipy.json"
csv_candidates = ()
json_candidates = ()
if preferred_csv.exists():
csv_candidates.append(preferred_csv)
if preferred_json.exists():
json_candidates.append(preferred_json)
csv_candidates += listing(project_dir.glob("*.csv")) + listing(project_dir.glob("**/*.csv"))
json_candidates += listing(project_dir.glob("*.json")) + listing(project_dir.glob("**/*.json"))
def uniq(paths):
seen = set()
out = ()
for p in paths:
p = p.resolve()
if p not in seen and p.is_file():
seen.add(p)
out.append(p)
return out
csv_candidates = uniq(csv_candidates)
json_candidates = uniq(json_candidates)
def pick_best(paths):
if not paths:
return None
paths = sorted(paths, key=lambda p: p.stat().st_mtime, reverse=True)
return paths(0)
return proc.returncode, pick_best(csv_candidates), pick_best(json_candidates)
rc, csv_report, json_report = run_complexipy_cli(root, MAX_ALLOWED)
Wir analysieren eine echte Quelldatei mithilfe der Python-API und führen dann die komplexe CLI für das gesamte Projekt aus. Wir führen die CLI aus dem richtigen Arbeitsverzeichnis aus, um zuverlässig Berichte zu erstellen. Dieser Schritt verbindet die lokale API-Nutzung mit statischen Analyse-Workflows im Produktionsstil.
df = None
if csv_report and csv_report.exists():
df = pd.read_csv(csv_report)
elif json_report and json_report.exists():
knowledge = json.masses(json_report.read_text())
if isinstance(knowledge, listing):
df = pd.DataFrame(knowledge)
elif isinstance(knowledge, dict):
if "information" in knowledge and isinstance(knowledge("information"), listing):
df = pd.DataFrame(knowledge("information"))
elif "outcomes" in knowledge and isinstance(knowledge("outcomes"), listing):
df = pd.DataFrame(knowledge("outcomes"))
else:
df = pd.json_normalize(knowledge)
if df is None:
elevate RuntimeError("No report produced")
def explode_functions_table(df_in):
if "capabilities" in df_in.columns:
tmp = df_in.explode("capabilities", ignore_index=True)
if tmp("capabilities").notna().any() and isinstance(tmp("capabilities").dropna().iloc(0), dict):
fn = pd.json_normalize(tmp("capabilities"))
base = tmp.drop(columns=("capabilities"))
return pd.concat((base.reset_index(drop=True), fn.reset_index(drop=True)), axis=1)
return tmp
return df_in
fn_df = explode_functions_table(df)
col_map = {}
for c in fn_df.columns:
lc = c.decrease()
if lc in ("path", "file", "filename", "module"):
col_map(c) = "path"
if ("perform" in lc and "title" in lc) or lc in ("perform", "func", "function_name"):
col_map(c) = "perform"
if lc == "title" and "perform" not in fn_df.columns:
col_map(c) = "perform"
if "complexity" in lc and "allowed" not in lc and "max" not in lc:
col_map(c) = "complexity"
if lc in ("line_start", "linestart", "start_line", "startline"):
col_map(c) = "line_start"
if lc in ("line_end", "lineend", "end_line", "endline"):
col_map(c) = "line_end"
fn_df = fn_df.rename(columns=col_map)
Wir laden die generierten Komplexitätsberichte in Pandas und normalisieren sie in eine Tabelle auf Funktionsebene. Wir verarbeiten mehrere mögliche Berichtsschemata, um den Workflow stabil zu halten. Diese strukturierte Darstellung ermöglicht es uns, mit Commonplace-Datenanalysetools über die Komplexität nachzudenken.
if "complexity" in fn_df.columns:
fn_df("complexity") = pd.to_numeric(fn_df("complexity"), errors="coerce")
plt.determine()
fn_df("complexity").dropna().plot(variety="hist", bins=20)
plt.title("Cognitive Complexity Distribution (capabilities)")
plt.xlabel("complexity")
plt.ylabel("depend")
plt.present()
def refactor_hints(complexity):
if complexity >= 20:
return (
"Break up into smaller pure capabilities",
"Exchange deep nesting with guard clauses",
"Extract complicated boolean predicates"
)
if complexity >= 12:
return (
"Extract inside logic into helpers",
"Flatten conditionals",
"Use dispatch tables"
)
if complexity >= 8:
return (
"Cut back nesting",
"Early returns"
)
return ("Acceptable complexity")
if "complexity" in fn_df.columns and "perform" in fn_df.columns:
for _, r in fn_df.sort_values("complexity", ascending=False).head(8).iterrows():
cx = float(r("complexity")) if pd.notna(r("complexity")) else None
if cx is None:
proceed
print(r("perform"), cx, refactor_hints(cx))
print("✅ Tutorial full.")
Wir visualisieren die Verteilung der kognitiven Komplexität und leiten Refactoring-Anleitungen aus numerischen Schwellenwerten ab. Wir übersetzen abstrakte Komplexitätswerte in konkrete technische Maßnahmen. Es schließt den Kreis, indem es die Messung direkt mit Entscheidungen zur Wartbarkeit verknüpft.
Abschließend stellten wir eine praktische, reproduzierbare Pipeline zur Prüfung der kognitiven Komplexität in Python-Projekten mithilfe von complexipy vor. Wir haben gezeigt, wie wir von der Advert-hoc-Inspektion zu datengesteuerten Überlegungen zur Codestruktur übergehen, risikoreiche Funktionen identifizieren und umsetzbare Refactoring-Anleitungen auf der Grundlage quantifizierter Schwellenwerte bereitstellen können. Der Workflow ermöglicht es uns, frühzeitig über die Wartbarkeit nachzudenken, Komplexitätsbudgets konsequent durchzusetzen und Codebasen mit Klarheit und Zuversicht zu entwickeln, anstatt uns ausschließlich auf die Instinct zu verlassen.
Schauen Sie sich das an VOLLSTÄNDIGE CODES hier. Sie können uns auch gerne weiter folgen Twitter und vergessen Sie nicht, bei uns mitzumachen 100.000+ ML SubReddit und Abonnieren Unser E-newsletter. Warten! Bist du im Telegram? Jetzt können Sie uns auch per Telegram kontaktieren.

