Maison  >  Article  >  développement back-end  >  Concevoir un outil de statistiques de code à l'aide de Python

Concevoir un outil de statistiques de code à l'aide de Python

不言
不言original
2018-04-04 16:57:571426parcourir

Cet article présente principalement des informations pertinentes sur l'utilisation de Python pour concevoir un outil de statistiques de code, notamment le nombre de fichiers, le nombre de lignes de code, le nombre de lignes de commentaires et le nombre de lignes vides. Amis intéressés, merci de suivre l'éditeur de Script House pour y jeter un oeil

Question

Concevoir un programme pour compter les statistiques d'un projet Le nombre de lignes de code, y compris le nombre de fichiers, les lignes de code, le nombre de lignes de commentaires et le nombre de lignes vides. Essayez d'être plus flexible dans la conception en saisissant différents paramètres pour compter les éléments dans différentes langues, par exemple :

# type用于指定文件类型
python counter.py --type python

Sortie :

fichiers :10
code_lines:200
commentaires:100
blancs:20

Analyse

C'est une question de conception qui semble très simple, mais qui est un peu compliquée à résoudre. Nous pouvons réduire le problème tant que nous pouvons compter correctement le nombre de lignes de code dans un fichier, puis compter un répertoire. n'est pas un problème. Le plus compliqué concerne les commentaires, en prenant Python comme exemple, les lignes de code de commentaire ont les situations suivantes :

1. Commentaires sur une seule ligne commençant par un signe dièse

.

# Commentaires sur une seule ligne

2. Lorsque les commentaires sur plusieurs lignes sont sur la même ligne

"""Ceci est un commentaire sur plusieurs lignes"""
'''Ceci est également un commentaire multi-ligne'''
3. Commentaires multi-lignes

"""
Ces trois lignes sont toutes des symboles de commentaire
"""

Notre idée est d'analyser ligne par ligne. Les commentaires multilignes nécessitent un identifiant supplémentaire in_multi_comment Pour identifier si la ligne actuelle est dans un commentaire multiligne. La valeur par défaut est False Lorsque le commentaire multiligne démarre. il est défini sur True et lorsque le prochain commentaire multiligne est rencontré, il est défini sur False. Le code entre le symbole de début d'un commentaire multiligne et le symbole de fin suivant doit appartenir à la ligne commentée.

Points de connaissances

Comment lire correctement les fichiers, lire les fichiers lors du traitement des chaînes, méthodes courantes de chaînes

Version simplifiée

Nous itérons étape par étape, en implémentant d'abord une version simplifiée du programme, qui ne compte qu'un seul fichier de code Python, et ne considère pas le multi-ligne commentaires Dans ce cas, il s'agit d'une fonction que toute personne ayant débuté avec Python peut réaliser. Le point clé est qu'après avoir lu chaque ligne, utilisez d'abord la méthode strip() pour supprimer les espaces et les retours chariot des deux côtés de la chaîne

# -*- coding: utf-8 -*-
"""
只能统计单行注释的py文件
"""
def parse(path):
 comments = 0
 blanks = 0
 codes = 0
 with open(path, encoding='utf-8') as f:
 for line in f.readlines():
  line = line.strip()
  if line == "":
  blanks += 1
  elif line.startswith("#"):
  comments += 1
  else:
  codes += 1
 return {"comments": comments, "blanks": blanks, "codes": codes}
if __name__ == '__main__':
 print(parse("xxx.py"))

Version de commentaires sur plusieurs lignes

Si vous ne pouvez compter que le code des commentaires sur une seule ligne, cela n'a que peu d'importance en résolvant les statistiques du multi. -les commentaires en ligne peuvent-ils être considérés comme un véritable statisticien de code

# -*- coding: utf-8 -*-
"""

Peut compter les fichiers py contenant des commentaires sur plusieurs lignes

"""
def parse(path):
 in_multi_comment = False # 多行注释符标识符号
 comments = 0
 blanks = 0
 codes = 0
 with open(path, encoding="utf-8") as f:
 for line in f.readlines():
  line = line.strip()
  # 多行注释中的空行当做注释处理
  if line == "" and not in_multi_comment:
  blanks += 1
  # 注释有4种
  # 1. # 井号开头的单行注释
  # 2. 多行注释符在同一行的情况
  # 3. 多行注释符之间的行
  elif line.startswith("#") or \
    (line.startswith('"""') and line.endswith('"""') and len(line)) > 3 or \
   (line.startswith("'''") and line.endswith("'''") and len(line) > 3) or \
   (in_multi_comment and not (line.startswith('"""') or line.startswith("'''"))):
  comments += 1
  # 4. 多行注释符的开始行和结束行
  elif line.startswith('"""') or line.startswith("'''"):
  in_multi_comment = not in_multi_comment
  comments += 1
  else:
  codes += 1
 return {"comments": comments, "blanks": blanks, "codes": codes}
if __name__ == '__main__':
 print(parse("xxx.py"))

Dans le quatrième cas ci-dessus, lorsqu'un symbole de commentaire multiligne est rencontré, l'opération clé consiste à inverser l'identifiant in_multi_comment, au lieu de simplement le définir sur False ou True. la première fois qu'il rencontre """, c'est Vrai, et la deuxième fois qu'il rencontre """ La première fois que """ est rencontré, c'est le caractère de fin du commentaire multiligne, et la négation est Faux, et ainsi de suite. La troisième fois, c'est le début, la négation est à nouveau vraie.

Alors, comment juger si d'autres langages doivent réécrire une fonction d'analyse ? Si vous observez attentivement, les quatre situations de commentaires multilignes peuvent résumer quatre conditions de jugement, car la plupart des langues ont des commentaires sur une seule ligne et des commentaires multilignes, mais leurs symboles sont différents.

CONF = {"py": {"start_comment": ['"""', "'''"], "end_comment": ['"""', "'''"], "single": "#"},
 "java": {"start_comment": ["/*"], "end_comment": ["*/"], "single": "//"}}
start_comment = CONF.get(exstansion).get("start_comment")
end_comment = CONF.get(exstansion).get("end_comment")
cond2 = False
cond3 = False
cond4 = False
for index, item in enumerate(start_comment):
 cond2 = line.startswith(item) and line.endswith(end_comment[index]) and len(line) > len(item)
 if cond2:
 break
for item in end_comment:
 if line.startswith(item):
 cond3 = True
 break
for item in start_comment+end_comment:
 if line.startswith(item):
 cond4 = True
 break
if line == "" and not in_multi_comment:
 blanks += 1
# 注释有4种
# 1. # 井号开头的单行注释
# 2. 多行注释符在同一行的情况
# 3. 多行注释符之间的行
elif line.startswith(CONF.get(exstansion).get("single")) or cond2 or \
 (in_multi_comment and not cond3):
 comments += 1
# 4. 多行注释符分布在多行时,开始行和结束行
elif cond4:
 in_multi_comment = not in_multi_comment
 comments += 1
else:
 codes += 1

Une seule constante de configuration est nécessaire pour marquer les symboles des commentaires monolignes et multilignes dans toutes les langues, correspondant à cond1 à cond4. . La tâche restante consiste à analyser plusieurs fichiers, ce qui peut être effectué à l'aide de la méthode os.walk.

def counter(path):
 """
 可以统计目录或者某个文件
 :param path:
 :return:
 """
 if os.path.isdir(path):
 comments, blanks, codes = 0, 0, 0
 list_dirs = os.walk(path)
 for root, dirs, files in list_dirs:
  for f in files:
  file_path = os.path.join(root, f)
  stats = parse(file_path)
  comments += stats.get("comments")
  blanks += stats.get("blanks")
  codes += stats.get("codes")
 return {"comments": comments, "blanks": blanks, "codes": codes}
 else:
 return parse(path)

Bien sûr, si vous souhaitez perfectionner ce programme, il reste encore beaucoup de travail à faire, y compris l'analyse en ligne de commande, et uniquement l'analyse un certain paramètre basé sur la langue des paramètres spécifiés.

Supplément :

Implémentation Python de l'outil de comptage de lignes de code

Nous souhaitons souvent count Le nombre de lignes de code du projet, mais si vous souhaitez avoir une fonction statistique plus complète, ce n'est peut-être pas si simple. Aujourd'hui, nous allons voir comment utiliser python pour implémenter un outil de statistiques de ligne de code.

Idée :

Récupérez d'abord tous les fichiers, puis comptez le nombre de lignes de code dans chaque fichier, et enfin ajoutez le nombre de lignes.

Fonctions implémentées :

Comptez le nombre de lignes dans chaque fichier
Comptez le nombre total de lignes
Comptez le temps d'exécution ;
Prise en charge des fichiers statistiques spécifiés, exclusion des types de fichiers qui ne veulent pas être comptés ;
Comptez récursivement le nombre de lignes de fichiers sous le dossier, y compris les sous-fichiers ;

Exclure les blancs ; lignes ;

# coding=utf-8
import os
import time
basedir = '/root/script'
filelists = []
# 指定想要统计的文件类型
whitelist = ['php', 'py']
#遍历文件, 递归遍历文件夹中的所有
def getFile(basedir):
 global filelists
 for parent,dirnames,filenames in os.walk(basedir):
  #for dirname in dirnames:
  # getFile(os.path.join(parent,dirname)) #递归
  for filename in filenames:
   ext = filename.split('.')[-1]
   #只统计指定的文件类型,略过一些log和cache文件
   if ext in whitelist:
    filelists.append(os.path.join(parent,filename))
#统计一个文件的行数
def countLine(fname):
 count = 0
 for file_line in open(fname).xreadlines():
  if file_line != '' and file_line != '\n': #过滤掉空行
   count += 1
 print fname + '----' , count
 return count
if __name__ == '__main__' :
 startTime = time.clock()
 getFile(basedir)
 totalline = 0
 for filelist in filelists:
  totalline = totalline + countLine(filelist)
 print 'total lines:',totalline
 print 'Done! Cost Time: %0.2f second' % (time.clock() - startTime)


Résultat :

[root@pythontab script]# python countCodeLine.py
/root/script /test/gametest.php---- 16
/root/script/smtp.php---- 284
/root/script/gametest.php- --- 16
/root/script /countCodeLine.py---- 33
/root/script/sendmail.php---- 17
/root/script/test/gametest.php- --- 16
lignes totales : 382
Terminé ! Coût Temps : 0,00 seconde
[root@pythontab script]#

Compte uniquement les fichiers php et python, ce qui est très pratique.

Recommandations associées :

Exemple de partage complet de la mise en œuvre de la fonction du calculateur de conception Python

Visiteurs et observations dans la programmation de modèles de conception Python Introduction à l'utilisateur exemples de modes


Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn