Comment implémenter l'outil de statistiques de code en Python

php中世界最好的语言
Libérer: 2018-04-09 16:02:47
original
1459 Les gens l'ont consulté

Cette fois, je vais vous montrer comment implémenter l'outil de statistiques de code en Python. Quelles sont les précautions pour implémenter l'outil de statistiques de code en Python. Voici des cas pratiques, jetons un coup d'œil.

Question

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

# type用于指定文件类型
python counter.py --type python
Copier après la connexion

Sortie :

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

Analyse

Celle-ci a l'air simple mais est un peu compliquée Nous pouvons réduire le problème. Tant que nous pouvons compter correctement le nombre de lignes de code dans un fichier, le comptage d'un répertoire n'est pas un problème. Le plus compliqué concerne les commentaires multilignes. à titre d'exemple, les lignes de code de commentaire sont les suivantes Plusieurs situations :

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

# Commentaires sur une seule ligne

2. -commentaires sur la même ligne

"""Ceci est un commentaire multi-lignes"""
'''Ceci est aussi un commentaire multi-lignes'''
3. caractère de commentaire de ligne

"""
Ces 3 lignes sont toutes le caractère de commentaire
"""

Notre idée est d'analyser ligne par ligne les commentaires multilignes sont requis. un identifiant supplémentaire in_multi_comment pour identifier si la ligne actuelle est dans un caractère de commentaire multiligne. La valeur par défaut est False, définie sur True lorsqu'un commentaire multiligne commence et définie sur False lorsque le caractère de commentaire multiligne suivant est rencontré. 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 un fichier, et le fichier lu doit être une chaîne Méthodes courantes pour le traitement des chaînes

Version simplifiée

Nous allons itérer étape par étape, implémenter d'abord une version simplifiée du programme, et ne compte que Python Un seul fichier de code, quels que soient les commentaires sur plusieurs lignes, est une fonction que toute personne novice en 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"))
Copier après la connexion

Version commentaire multi-lignes

Si vous ne pouvez compter que le code des commentaires sur une seule ligne, cela n'a que peu d'importance. Seules les statistiques des commentaires sur plusieurs lignes peuvent être considérées comme un véritable statisticien de code

.
# -*- coding: utf-8 -*-
"""
Copier après la connexion

Il peut compter le nombre de lignes de code qu'il contient. Fichier py avec des commentaires de ligne

"""
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"))
Copier après la connexion

Dans le quatrième cas ci-dessus, lorsque vous rencontrez des symboles de commentaires multilignes, il est préférable d'inverser l'identifiant in_multi_comment. l'opération de touche, plutôt que de simplement la définir sur False ou True. Lorsque """ est rencontré pour la première fois, il est vrai. Lorsque """ est rencontré pour la deuxième fois, il s'agit du caractère de fin de la multiligne. commentaire. S'il est nié, c'est Faux et ainsi de suite. La troisième fois, c'est le début, et s'il est nié, c'est à nouveau Vrai.

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
Copier après la connexion

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)
Copier après la connexion

Bien sûr, il reste encore beaucoup de travail à faire pour perfectionner ce programme, y compris l'analyse en ligne de commande et l'analyse d'un certain langage uniquement en fonction de 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.

Fonction implémentée :

统计每个文件的行数;
统计总行数;
统计运行时间;
支持指定统计文件类型,排除不想统计的文件类型;
递归统计文件夹下包括子文件件下的文件的行数;

排除空行;

# 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)
Copier après la connexion

结果:

[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
total lines: 382
Done! Cost Time: 0.00 second
[root@pythontab script]#

相信看了本文案例你已经掌握了方法,更多精彩请关注php中文网其它相关文章!

推荐阅读:

怎么对numpy里数组元素赋统一的值

numpy数组与矩阵的乘法怎么使用

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!

Étiquettes associées:
source:php.cn
Déclaration de ce site Web
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
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal
À propos de nous Clause de non-responsabilité Sitemap
Site Web PHP chinois:Formation PHP en ligne sur le bien-être public,Aidez les apprenants PHP à grandir rapidement!