用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
直接命令不会经过审查 Prompt;运行前请先检查来源。
npx skills add https://github.com/microwind/ai-skills --skill python命令会保持在同一行。复制前请横向滚动并检查完整内容。
想先保存到本地?可下载 SkillsMP 当前能够提供的文件。
基于 SOC 职业分类
正在显示 SKILL.md
| name | Python分析器 |
| description | 当进行Python代码审查、性能优化、类型安全检查或测试策略规划时,分析Python代码质量和最佳实践。 |
| license | MIT |
Python让编写糟糕代码变得容易。分析代码质量以防止技术债务。
核心原则: Python让编写糟糕代码变得容易。分析代码质量以防止技术债务。
始终:
触发短语:
问题:
不符合PEP 8编码规范
错误示例:
- 变量名使用驼峰命名
- 行长度超过79字符
- 缺少空行分隔
- 导入语句不规范
解决方案:
1. 使用black自动格式化
2. 配置flake8检查
3. 使用isort整理导入
4. 遵循PEP 8指南
问题:
Python代码性能低下
错误示例:
- 在循环中使用+拼接字符串
- 不必要的列表推导
- 全局变量访问
- 缺少缓存机制
解决方案:
1. 使用join拼接字符串
2. 优化数据结构选择
3. 使用局部变量
4. 实现缓存策略
问题:
缺少类型注解导致运行时错误
错误示例:
- 函数参数无类型提示
- 返回值类型不明确
- 可选参数未标注
- 泛型使用不当
解决方案:
1. 添加类型注解
2. 使用Optional标注可选值
3. 使用TypeVar定义泛型
4. 运行mypy检查
import ast
import os
import re
from collections import defaultdict
from typing import List, Dict, Any, Optional
from dataclasses import dataclass
from pathlib import Path
@dataclass
class CodeIssue:
"""代码问题"""
file_path: str
line_number: int
column: int
severity: str # error, warning, info
message: str
rule_id: str
suggestion: Optional[str] = None
@dataclass
class FunctionMetrics:
"""函数指标"""
name: str
line_start: int
line_end: int
complexity: int
arguments: int
returns: int
docstring: bool
type_annotations: bool
@dataclass
class ClassMetrics:
"""类指标"""
name: str
line_start: int
line_end: int
methods: int
attributes: int
inheritance_depth:
docstring:
:
():
.config = config .get_default_config()
.issues: [CodeIssue] = []
.function_metrics: [FunctionMetrics] = []
.class_metrics: [ClassMetrics] = []
.imports: [, []] = defaultdict()
.complexity_threshold = .config.get(, )
() -> :
{
: ,
: ,
: ,
: ,
: ,
: ,
: ,
:
}
() -> [, ]:
:
(file_path, , encoding=) f:
content = f.read()
tree = ast.parse(content, filename=file_path)
.issues = []
.function_metrics = []
.class_metrics = []
.imports = defaultdict()
.check_style(file_path, content)
.analyze_ast(tree, file_path)
.check_complexity(tree, file_path)
.check_type_safety(tree, file_path)
.check_documentation(tree, file_path)
{
: file_path,
: .issues,
: .function_metrics,
: .class_metrics,
: (.imports),
: .generate_summary()
}
SyntaxError e:
{
: file_path,
: ,
: [CodeIssue(
file_path=file_path,
line_number=e.lineno ,
column=e.offset ,
severity=,
message=,
rule_id=
)]
}
Exception e:
{
: file_path,
: ,
: []
}
() -> [, ]:
results = []
all_issues = []
root, dirs, files os.walk(directory):
dirs[:] = [d d dirs d.startswith() d [, , ]]
file files:
file.endswith():
file_path = os.path.join(root, file)
result = .analyze_file(file_path)
results.append(result)
all_issues.extend(result.get(, []))
{
: directory,
: results,
: (all_issues),
: .categorize_issues(all_issues),
: .generate_recommendations(all_issues)
}
() -> :
lines = content.split()
line_num, line (lines, ):
(line) > .config[]:
.issues.append(CodeIssue(
file_path=file_path,
line_number=line_num,
column=.config[],
severity=,
message=,
rule_id=,
suggestion=
))
line.endswith():
.issues.append(CodeIssue(
file_path=file_path,
line_number=line_num,
column=(line.rstrip()),
severity=,
message=,
rule_id=,
suggestion=
))
line:
.issues.append(CodeIssue(
file_path=file_path,
line_number=line_num,
column=line.find(),
severity=,
message=,
rule_id=,
suggestion=
))
() -> :
node ast.walk(tree):
(node, ast.Import):
alias node.names:
.imports[].append(alias.name)
(node, ast.ImportFrom):
module = node.module
alias node.names:
.imports[].append()
node ast.walk(tree):
(node, ast.FunctionDef):
.analyze_function(node, file_path)
(node, ast.ClassDef):
.analyze_class(node, file_path)
() -> :
complexity = .calculate_complexity(node)
args = (node.args.args) + (node.args.kwonlyargs)
node.args.vararg:
args +=
node.args.kwarg:
args +=
returns = ([n n ast.walk(node) (n, ast.Return)])
has_docstring = (ast.get_docstring(node) )
has_type_annotations = (
(arg.annotation arg node.args.args)
(node.returns )
)
metrics = FunctionMetrics(
name=node.name,
line_start=node.lineno,
line_end=node.end_lineno node.lineno,
complexity=complexity,
arguments=args,
returns=returns,
docstring=has_docstring,
type_annotations=has_type_annotations
)
.function_metrics.append(metrics)
complexity > .complexity_threshold:
.issues.append(CodeIssue(
file_path=file_path,
line_number=node.lineno,
column=,
severity=,
message=,
rule_id=,
suggestion=
))
has_docstring .config[]:
.issues.append(CodeIssue(
file_path=file_path,
line_number=node.lineno,
column=,
severity=,
message=,
rule_id=,
suggestion=
))
has_type_annotations .config[]:
.issues.append(CodeIssue(
file_path=file_path,
line_number=node.lineno,
column=,
severity=,
message=,
rule_id=,
suggestion=
))
() -> :
methods =
attributes =
item node.body:
(item, ast.FunctionDef):
methods +=
(item, ast.Assign):
target item.targets:
(target, ast.Name):
attributes +=
inheritance_depth = .calculate_inheritance_depth(node)
has_docstring = (ast.get_docstring(node) )
metrics = ClassMetrics(
name=node.name,
line_start=node.lineno,
line_end=node.end_lineno node.lineno,
methods=methods,
attributes=attributes,
inheritance_depth=inheritance_depth,
docstring=has_docstring
)
.class_metrics.append(metrics)
inheritance_depth > :
.issues.append(CodeIssue(
file_path=file_path,
line_number=node.lineno,
column=,
severity=,
message=,
rule_id=,
suggestion=
))
has_docstring .config[]:
.issues.append(CodeIssue(
file_path=file_path,
line_number=node.lineno,
column=,
severity=,
message=,
rule_id=,
suggestion=
))
() -> :
complexity =
child ast.walk(node):
(child, (ast.If, ast.While, ast.For, ast.AsyncFor)):
complexity +=
(child, ast.ExceptHandler):
complexity +=
(child, ast.With, ast.AsyncWith):
complexity +=
(child, ast.BoolOp):
complexity += (child.values) -
complexity
() -> :
node.bases:
max_depth =
base node.bases:
(base, ast.Name):
max_depth = (max_depth, )
max_depth
() -> :
node ast.walk(tree):
(node, (ast.For, ast.While, ast.If)):
depth = .calculate_nesting_depth(node)
depth > :
.issues.append(CodeIssue(
file_path=file_path,
line_number=node.lineno,
column=,
severity=,
message=,
rule_id=,
suggestion=
))
() -> :
max_depth = current_depth
child ast.iter_child_nodes(node):
(child, (ast.For, ast.While, ast.If, ast.With, ast.Try)):
child_depth = .calculate_nesting_depth(child, current_depth + )
max_depth = (max_depth, child_depth)
max_depth
() -> :
node ast.walk(tree):
(node, ast.FunctionDef):
.check_function_types(node, file_path)
(node, ast.Attribute):
.check_none_safety(node, file_path)
() -> :
.config[]:
arg node.args.args:
arg.annotation:
.issues.append(CodeIssue(
file_path=file_path,
line_number=node.lineno,
column=,
severity=,
message=,
rule_id=,
suggestion=
))
node.returns:
.issues.append(CodeIssue(
file_path=file_path,
line_number=node.lineno,
column=,
severity=,
message=,
rule_id=,
suggestion=
))
() -> :
(node.value, ast.Name) node.value. == :
.issues.append(CodeIssue(
file_path=file_path,
line_number=node.lineno,
column=node.col_offset,
severity=,
message=,
rule_id=,
suggestion=
))
() -> :
ast.get_docstring(tree) .config[]:
.issues.append(CodeIssue(
file_path=file_path,
line_number=,
column=,
severity=,
message=,
rule_id=,
suggestion=
))
() -> [, ]:
total_issues = (.issues)
error_count = ([i i .issues i.severity == ])
warning_count = ([i i .issues i.severity == ])
info_count = ([i i .issues i.severity == ])
{
: total_issues,
: error_count,
: warning_count,
: info_count,
: (.function_metrics),
: (.class_metrics),
: .calculate_average_complexity()
}
() -> :
.function_metrics:
total_complexity = (f.complexity f .function_metrics)
total_complexity / (.function_metrics)
() -> [, [CodeIssue]]:
categorized = {
: [],
: [],
: []
}
issue issues:
categorized[issue.severity].append(issue)
categorized
() -> [[, ]]:
recommendations = []
issue_counts = defaultdict()
issue issues:
issue_counts[issue.rule_id] +=
issue_counts[] > :
recommendations.append({
: ,
: ,
: ,
:
})
issue_counts[] > :
recommendations.append({
: ,
: ,
: ,
:
})
issue_counts[] > :
recommendations.append({
: ,
: ,
: ,
:
})
issue_counts[] > :
recommendations.append({
: ,
: ,
: ,
:
})
recommendations
():
analyzer = PythonAnalyzer()
result = analyzer.analyze_file()
()
()
directory_result = analyzer.analyze_directory()
()
()
rec directory_result[]:
()
__name__ == :
main()
import time
import cProfile
import pstats
import io
from functools import wraps
from typing import Callable, Dict, Any, List
from dataclasses import dataclass
@dataclass
class PerformanceMetric:
"""性能指标"""
function_name: str
execution_time: float
call_count: int
memory_usage: int
cpu_usage: float
class PythonPerformanceAnalyzer:
def __init__(self):
self.metrics: List[PerformanceMetric] = []
self.profiles: Dict[str, cProfile.Profile] = {}
def profile_function(self, func: Callable) -> Callable:
"""函数性能分析装饰器"""
@wraps(func)
def wrapper(*args, **kwargs):
# 创建性能分析器
profiler = cProfile.Profile()
# 开始分析
start_time = time.time()
profiler.enable()
try:
result = func(*args, **kwargs)
result
:
profiler.disable()
end_time = time.time()
execution_time = end_time - start_time
.record_metric(func.__name__, execution_time, profiler)
.profiles[func.__name__] = profiler
result
wrapper
() -> :
stats = pstats.Stats(profiler)
call_count =
func_info, (calls, _, _, _, _) stats.stats.items():
func_info[] == func_name:
call_count = calls
metric = PerformanceMetric(
function_name=func_name,
execution_time=execution_time,
call_count=call_count,
memory_usage=,
cpu_usage=
)
.metrics.append(metric)
() -> [, ]:
func_name .profiles:
{: }
profiler = .profiles[func_name]
stats = pstats.Stats(profiler)
hotspots = []
func_info, (calls, total_time, cum_time, _, _) stats.stats.items():
hotspots.append({
: func_info[],
: calls,
: total_time,
: cum_time
})
hotspots.sort(key= x: x[], reverse=)
{
: func_name,
: hotspots[:],
: (h[] h hotspots),
: (h[] h hotspots)
}
() -> []:
report = .get_performance_report(func_name)
suggestions = []
report:
suggestions
hotspots = report[]
hotspot hotspots[:]:
hotspot[] > :
suggestions.append(
)
hotspot[] > :
suggestions.append(
)
suggestions
():
time.sleep()
result = (i * i i ())
result
():
_ ():
slow_function()
analyzer = PythonPerformanceAnalyzer()
report = analyzer.get_performance_report()
(, report)
suggestions = analyzer.optimize_suggestions()
(, suggestions)
__name__ == :
main()