如何统计Python程序中的独立Token数量?求相关工具推荐
统计代码独立Token数量的实现方案及跨语言工具
Python 实现方案
用标准库 tokenize 直接统计Token
Python自带的tokenize模块是最简便的Token统计方案,它能精准解析代码的词法单元,还可以过滤掉注释、空白等非业务相关的Token。
以下是可直接运行的脚本:
import tokenize from io import BytesIO def count_valid_tokens(code: str) -> int: # 将代码转为字节流适配tokenize输入格式 byte_code = code.encode('utf-8') # 生成所有Token tokens = list(tokenize.tokenize(BytesIO(byte_code).readline)) # 定义需要统计的有效Token类型(可根据需求调整) valid_types = { tokenize.NAME, tokenize.NUMBER, tokenize.STRING, tokenize.OP, tokenize.NEWLINE, tokenize.INDENT, tokenize.DEDENT } return sum(1 for tok in tokens if tok.type in valid_types) # 测试你给出的示例代码 sample_code = 'grammar = grammar_path.read_text(encoding="UTF-8")' print(count_valid_tokens(sample_code))
注:这段代码统计的标准Token数为10(对应每个独立词法单元),如果你需要更粗粒度的统计(比如把grammar_path.read_text合并为一个单元),可以在Token遍历逻辑中添加合并规则,比如连续的NAME+.+NAME视为一个整体。
AST 辅助方案(适用于更抽象的代码单元统计)
如果你需要统计的是语法级别的单元而非纯Token,Python的ast模块可以解析代码生成抽象语法树,遍历节点统计语句、函数调用等单元,但它不直接对应Token级别的计数,适合更宏观的复杂度分析。
其他语言的同类工具
- JavaScript/TypeScript:使用
acorn或@babel/parser,两者都能生成Token流并统计。示例(acorn):const acorn = require('acorn'); const code = `const grammar = grammarPath.readText({encoding: "UTF-8"});`; const tokens = acorn.tokenize(code); // 过滤空白和注释后统计 const validCount = tokens.filter(t => t.type !== 'whitespace' && t.type !== 'comment').length; console.log(validCount); - Java:可以用JDK自带的
java.io.StreamTokenizer做基础Token统计,复杂场景用ANTLR生成定制化的词法解析器,精准控制Token规则。 - C/C++:借助
clang的API实现Token扫描,或用flex生成自定义词法分析器;也有轻量工具如token-count直接统计。 - Go:用标准库
go/scanner扫描代码生成Token,过滤无效类型后计数:package main import ( "fmt" "go/scanner" "go/token" ) func countTokens(code string) int { var s scanner.Scanner fset := token.NewFileSet() file := fset.AddFile("", fset.Base(), len(code)) s.Init(file, []byte(code), nil, scanner.ScanComments) count := 0 for { _, tok, _ := s.Scan() if tok == token.EOF { break } if tok != token.COMMENT && tok != token.WHITESPACE { count++ } } return count } func main() { code := `grammar := grammarPath.ReadText("UTF-8")` fmt.Println(countTokens(code)) } - Ruby:用自带的
Ripper模块做词法分析,过滤注释和空白后统计Token:require 'ripper' def count_tokens(code) tokens = Ripper.lex(code) tokens.reject { |t| [:on_comment, :on_sp, :on_nl].include?(t[1]) }.size end sample_code = 'grammar = grammar_path.read_text(encoding: "UTF-8")' puts count_tokens(sample_code)
内容的提问来源于stack exchange,提问作者Brendan Langfield
相关产品推荐
相关产品推荐

