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()