import re
import sys
import os
import ast
from tokenize import generate_tokens, COMMENT, STRING, NL, INDENT, DEDENT
import iodef extract_entities(filename):"""提取类和函数到单独文件"""with open(filename, 'r', encoding='utf-8') as f:content = f.read()# 计算总行数total_lines = content.count('\n') + 1long_function_threshold = max(80, total_lines // 12)# 初始化结果entities = []current_pos = 0# 尝试使用AST解析获取更准确的位置信息try:tree = ast.parse(content)ast_entities = []for node in tree.body:if isinstance(node, ast.ClassDef):start_line = node.linenoend_line = node.end_linenoast_entities.append(('class', node.name, start_line, end_line))elif isinstance(node, ast.FunctionDef):start_line = node.linenoend_line = node.end_linenoast_entities.append(('function', node.name, start_line, end_line))# 使用AST信息辅助提取lines = content.split('\n')for e_type, name, start_line, end_line in ast_entities:start_index = sum(len(line) + 1 for line in lines[:start_line-1])end_index = sum(len(line) + 1 for line in lines[:end_line]) - 1# 对于函数,检查是否为长函数if e_type == 'function':func_lines = end_line - start_line + 1if func_lines > long_function_threshold:func_content = content[start_index:end_index]entities.append(('function', name, start_index, end_index, func_content))# 类总是提取elif e_type == 'class':class_content = content[start_index:end_index]entities.append(('class', name, start_index, end_index, class_content))except SyntaxError:# 如果AST解析失败,使用基于缩进的方法return extract_entities_with_indent(content, total_lines, long_function_threshold)return entities, content, total_linesdef extract_entities_with_indent(content, total_lines, long_function_threshold):"""当AST解析失败时使用基于缩进的方法"""entities = []current_pos = 0# 类定义正则(支持装饰器和继承)class_pattern = re.compile(r'^([ \t]*)@?.*?\b(class|struct)\s+(\w+)\s*[\(:]?[^{:]*[:{]?', re.MULTILINE)# 函数定义正则(支持装饰器和类型注解)func_pattern = re.compile(r'^([ \t]*)@?.*?\b(def)\s+(\w+)\s*\([^{:]*\)\s*[^{:]*[:{]?', re.MULTILINE)# 提取类for match in class_pattern.finditer(content):indent = match.group(1)class_name = match.group(3)start_index = match.start()# 找到类体的结束位置end_index = find_block_end(content, start_index, indent)if end_index == -1:continueclass_content = content[start_index:end_index]entities.append(('class', class_name, start_index, end_index, class_content))current_pos = end_index# 提取函数(只提取顶级函数,忽略类内方法)for match in func_pattern.finditer(content):func_name = match.group(3)start_index = match.start()indent = match.group(1)# 跳过类内的方法if any(start_index > c_start and start_index < c_end for (t, _, c_start, c_end, _) in entities if t == 'class'):continue# 找到函数体的结束位置end_index = find_block_end(content, start_index, indent)if end_index == -1:continuefunc_content = content[start_index:end_index]func_lines = func_content.count('\n') + 1# 检查是否为长函数if func_lines > long_function_threshold:entities.append(('function', func_name, start_index, end_index, func_content))current_pos = end_index# 按起始位置排序entities.sort(key=lambda x: x[2])return entities, content, total_linesdef find_block_end(content, start_index, base_indent):"""找到代码块的结束位置"""base_indent_level = len(base_indent) if base_indent else 0current_index = start_indexstack = []in_string = Falsestring_char = Nonewhile current_index < len(content):char = content[current_index]# 处理字符串字面量if not in_string and char in ('"', "'"):in_string = Truestring_char = charelif in_string and char == string_char:# 检查是否是转义的引号if content[current_index-1] == '\\':# 检查转义字符本身是否被转义backslash_count = 0i = current_index - 1while i >= 0 and content[i] == '\\':backslash_count += 1i -= 1if backslash_count % 2 == 0:  # 偶数个反斜杠,引号未被转义in_string = Falsestring_char = Noneelse:in_string = Falsestring_char = Noneif in_string:current_index += 1continue# 处理括号if char in '([{':stack.append(char)elif char in ')]}':if not stack:return -1  # 不匹配的括号last_open = stack.pop()if (last_open == '(' and char != ')') or \(last_open == '[' and char != ']') or \(last_open == '{' and char != '}'):return -1  # 括号不匹配# 检查代码块结束if char == '\n':next_line_start = current_index + 1if next_line_start >= len(content):return next_line_start  # 文件结束# 检查下一行的缩进级别next_line_end = content.find('\n', next_line_start)if next_line_end == -1:next_line_end = len(content)next_line = content[next_line_start:next_line_end]indent_level = len(next_line) - len(next_line.lstrip())# 如果缩进小于基础缩进且没有未闭合的括号,则块结束if indent_level <= base_indent_level and not stack:# 确保不是空行或注释stripped_line = next_line.strip()if stripped_line and not stripped_line.startswith('#'):return next_line_startcurrent_index += 1return len(content)  # 到达文件末尾def write_entities(entities, content, filename):"""将实体写入文件并生成剩余内容"""# 创建输出目录base_name = os.path.splitext(os.path.basename(filename))[0]output_dir = f"{base_name}_split"os.makedirs(output_dir, exist_ok=True)# 提取覆盖范围covered_ranges = []for entity in entities:e_type, e_name, start, end, e_content = entity# 确保每个实体都写入单独的文件output_path = os.path.join(output_dir, f"{e_name}.py")with open(output_path, 'w', encoding='utf-8') as f:f.write(e_content)covered_ranges.append((start, end))# 生成剩余内容covered_ranges.sort(key=lambda x: x[0])remaining_parts = []last_pos = 0for start, end in covered_ranges:remaining_parts.append(content[last_pos:start])last_pos = endremaining_parts.append(content[last_pos:])remaining_content = ''.join(remaining_parts)# 写入剩余文件left_path = os.path.join(output_dir, "left.py")with open(left_path, 'w', encoding='utf-8') as f:f.write(remaining_content)return output_dirdef main():if len(sys.argv) != 2:print("Usage: python split_code.py <source_file.py>")sys.exit(1)filename = sys.argv[1]if not os.path.isfile(filename):print(f"Error: File not found - {filename}")sys.exit(1)try:entities, content, total_lines = extract_entities(filename)output_dir = write_entities(entities, content, filename)class_count = sum(1 for e in entities if e[0] == 'class')func_count = sum(1 for e in entities if e[0] == 'function')print(f"Processed {filename}:")print(f"- Total lines: {total_lines}")print(f"- Long function threshold: {max(80, total_lines//12)} lines")print(f"- Extracted: {class_count} classes, {func_count} long functions")print(f"- Output directory: {output_dir}")print(f"- Remaining code in: {os.path.join(output_dir, 'left.py')}")except Exception as e:print(f"Error processing file: {str(e)}")import tracebacktraceback.print_exc()sys.exit(1)if __name__ == "__main__":main()

需求: 

写一个python脚本,阅读python源代码,i, 把源文件中各个class 切分到文件中,文件名是类名,ii,长函数(代码行超过本文件长度1/12, 或者超过80行,两个条件满足一个即可)切分到文件中,文件名是函数名。 iii,剩余部分放在left.py文件中,谢谢

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/pingmian/91389.shtml
繁体地址,请注明出处:http://hk.pswp.cn/pingmian/91389.shtml
英文地址,请注明出处:http://en.pswp.cn/pingmian/91389.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

新型融合肽递送外泌体修饰可注射温敏水凝胶用于骨再生

温敏水凝胶因能模拟细胞外基质微环境&#xff0c;且具有原位注射性和形态适应性&#xff0c;在骨组织工程中应用广泛。小肠黏膜下层&#xff08;SIS&#xff09;作为天然细胞外基质来源&#xff0c;富含 I 型和 III 型胶原蛋白及多种生物活性因子&#xff0c;其制备的水凝胶在组…

SPI接口的4种模式(根据时钟极性和时钟相位)

SPI&#xff08;Serial Peripheral Interface&#xff09; 接口根据时钟极性&#xff08;CPOL&#xff09;和时钟相位&#xff08;CPHA&#xff09;的不同组合&#xff0c;共有 4种工作模式。这些模式决定了数据采样和传输的时序关系&#xff0c;是SPI通信中必须正确配置的关键…

Java:高频面试知识分享2

HashSet 和 TreeSet 的区别&#xff1f;底层实现&#xff1a;HashSet 基于 HashMap 实现&#xff0c;使用哈希表存储元素&#xff1b;TreeSet 基于 TreeMap&#xff0c;底层为红黑树。元素顺序&#xff1a;HashSet 无序&#xff1b;TreeSet 会根据元素的自然顺序或传入的 Compa…

C语言习题讲解-第九讲- 常见错误分类等

C语言习题讲解-第九讲- 常见错误分类等1. C程序常见的错误分类不包含&#xff1a;&#xff08; &#xff09;2. 根据下面递归函数&#xff1a;调用函数 Fun(2) &#xff0c;返回值是多少&#xff08; &#xff09;3. 关于递归的描述错误的是&#xff1a;&#xff08; &#x…

A∗算法(A-star algorithm)一种在路径规划和图搜索中广泛使用的启发式搜索算法

A∗A*A∗算法&#xff08;A-star algorithm&#xff09;是一种在路径规划和图搜索中广泛使用的启发式搜索算法&#xff0c;它结合了Dijkstra算法的广度优先搜索思想和启发式算法的效率优势&#xff0c;能够高效地找到从起点到终点的最短路径。 1. 基本原理 A*算法的核心是通过估…

UniappDay06

1.填写订单-渲染基本信息 静态结构&#xff08;分包&#xff09;封装请求API import { http } from /utils/http import { OrderPreResult } from /types/orderexport const getmemberOrderPreAPI () > {return http<OrderPreResult>({method: GET,url: /member/orde…

论文略读:GINGER: Grounded Information Nugget-Based Generation of Responses

SIGIR 2025用户日益依赖对话助手&#xff08;如 ChatGPT&#xff09;来满足多种信息需求&#xff0c;这些需求包括开放式问题、需要推理的间接回答&#xff0c;以及答案分布在多个段落中的复杂查询RAG试图通过在生成过程中引入检索到的信息来解决这些问题但如何确保回应的透明性…

从内部保护你的网络

想象一下&#xff0c;你是一家高端俱乐部的老板&#xff0c;商务贵宾们聚集在这里分享信息、放松身心。然后假设你雇佣了最顶尖的安保人员——“保镖”——站在门口&#xff0c;确保你准确掌握所有进出的人员&#xff0c;并确保所有人的安全。不妨想象一下丹尼尔克雷格和杜安约…

Redis 中 ZipList 的级联更新问题

ZipList 的结构ZipList 是 Redis 中用于实现 ZSet 的压缩数据结构&#xff0c;其元素采用连续存储方式&#xff0c;具有很高的内存紧凑性。ZipList 结构组成如下&#xff1a;zlbytes&#xff1a;4字节&#xff0c;记录整个ziplist的字节数zltail&#xff1a;4字节&#xff0c;记…

【苍穹外卖项目】Day05

&#x1f4d8;博客主页&#xff1a;程序员葵安 &#x1faf6;感谢大家点赞&#x1f44d;&#x1f3fb;收藏⭐评论✍&#x1f3fb; 一、Redis入门 Redis简介 Redis是一个基于内存的 key-value 结构数据库 基于内存存储&#xff0c;读写性能高适合存储热点数据&#xff08;热…

语音识别dolphin 学习笔记

目录 Dolphin简介 Dolphin 中共有 4 个模型&#xff0c;其中 2 个现在可用。 使用demo Dolphin简介 Dolphin 是由 Dataocean AI 和清华大学合作开发的多语言、多任务语音识别模型。它支持东亚、南亚、东南亚和中东的 40 种东方语言&#xff0c;同时支持 22 种汉语方言。该模…

视频生成中如何选择GPU或NPU?

在视频生成中选择GPU还是NPU&#xff0c;核心是根据场景需求、技术约束和成本目标来匹配两者的特性。以下是具体的决策框架和场景化建议&#xff1a; 核心决策依据&#xff1a;先明确你的“视频生成需求” 选择前需回答3个关键问题&#xff1a; 生成目标&#xff1a;视频分辨率…

从豆瓣小组到深度洞察:一个基于Python的舆情分析爬虫实践

文章目录 从豆瓣小组到深度洞察:一个基于Python的舆情分析爬虫实践 摘要 1. 背景 2. 需求分析 3. 技术选型与实现 3.1 总体架构 3.2 核心代码解析 4. 难点分析与解决方案 5. 总结与展望 对爬虫、逆向感兴趣的同学可以查看文章,一对一小班教学:https://blog.csdn.net/weixin_…

RustDesk 使用教程

说明&#xff1a; 使用RustDesk 需要在不同的电脑安装对应系统型号的客户端&#xff0c;然后再去云服务器安装一个服务端即可。 1、到网站下载客户端&#xff1a;https://rustdesk.com/zh-cn/ 两台电脑安装客户端。 2、在云服务器安装服务端 1&#xff09;官网教程&#xff1a;…

【C语言网络编程基础】TCP 服务器详解

在网络通信中&#xff0c;TCP&#xff08;Transmission Control Protocol&#xff0c;传输控制协议&#xff09;是一种可靠、面向连接的协议。一个 TCP 服务器正是基于这种协议&#xff0c;为客户端提供稳定的网络服务。本文将详细介绍 TCP 服务器的基本原理和工作流程。 一、什…

一篇就够!Windows上Docker Desktop安装 + 汉化完整指南(包含解决wsl更新失败方案)

前言 在现代软件开发和人工智能应用中&#xff0c;环境的稳定性和可移植性至关重要。Docker 作为一种轻量级的容器化技术&#xff0c;为开发者提供一致的运行环境&#xff0c;使得软件可以在不同平台上无缝运行&#xff0c;极大地提升了开发和部署的效率。无论是本地开发、测试…

设计模式(二十四)行为型:访问者模式详解

设计模式&#xff08;二十四&#xff09;行为型&#xff1a;访问者模式详解访问者模式&#xff08;Visitor Pattern&#xff09;是 GoF 23 种设计模式中最具争议性但也最强大的行为型模式之一&#xff0c;其核心价值在于将作用于某种数据结构中的各元素的操作分离出来&#xff…

USRP X440 和USRP X410 直接RF采样架构的优势

USRP X440 和USRP X410 直接RF采样架构的优势概述什么是直接RF采样&#xff1f;如何实现直接采样&#xff1f;什么情况下应考虑使用直接RF采样架构&#xff1f;概述 转换器技术每年都在发展。主要半导体公司的模数转换器(ADC)和数模转换器(DAC)的采样速率比十年前的产品快了好…

P4568 [JLOI2011] 飞行路线

P4568 [JLOI2011] 飞行路线 题目描述 Alice 和 Bob 现在要乘飞机旅行&#xff0c;他们选择了一家相对便宜的航空公司。该航空公司一共在 nnn 个城市设有业务&#xff0c;设这些城市分别标记为 000 到 n−1n-1n−1&#xff0c;一共有 mmm 种航线&#xff0c;每种航线连接两个城市…

MySQL 中的聚簇索引和非聚簇索引的区别

MySQL 中的聚簇索引和非聚簇索引的区别 总结性回答 聚簇索引和非聚簇索引的主要区别在于索引的组织方式和数据存储位置。聚簇索引决定了表中数据的物理存储顺序&#xff0c;一个表只能有一个聚簇索引&#xff1b;而非聚簇索引是独立于数据存储的额外结构&#xff0c;一个表可以…