最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

基于Python實現(xiàn)字符串規(guī)范檢查與修復(fù)程序

 更新時間:2025年10月31日 09:41:45   作者:weixin_30777913  
在Python開發(fā)中,代碼風(fēng)格的統(tǒng)一性對于項目的可維護性至關(guān)重要,本文介紹一個智能的Python字符串引號規(guī)范自動修復(fù)程序,它能夠自動檢測并修復(fù)代碼中的字符串引號使用不一致問題,有需要的可以參考下

在Python開發(fā)中,代碼風(fēng)格的統(tǒng)一性對于項目的可維護性至關(guān)重要。雖然PEP 8沒有強制規(guī)定字符串使用單引號還是雙引號,但許多團隊會選擇其中一種作為編碼規(guī)范。本文介紹一個智能的Python字符串引號規(guī)范自動修復(fù)程序,它能夠自動檢測并修復(fù)代碼中的字符串引號使用不一致問題。

完整實現(xiàn)代碼

#!/usr/bin/env python3
"""
Python字符串引號規(guī)范檢查與修復(fù)工具
自動檢查單引號字符串并建議替換為雙引號
"""

import ast
import tokenize
import argparse
import os
import sys
import json
from pathlib import Path
from typing import List, Dict, Tuple, Set, Any
import fnmatch

class StringQuoteChecker:
    """字符串引號檢查器"""
    
    def __init__(self):
        self.stats = {
            'files_processed': 0,
            'total_strings': 0,
            'single_quote_strings': 0,
            'replaced_strings': 0,
            'skipped_strings': 0,
            'error_files': 0,
            'issues_found': 0
        }
        self.issues = []
        
    def is_excluded_directory(self, filepath: str, exclude_dirs: List[str]) -> bool:
        """檢查是否在排除目錄中"""
        path = Path(filepath)
        for exclude_dir in exclude_dirs:
            if fnmatch.fnmatch(str(path), exclude_dir) or exclude_dir in path.parts:
                return True
        return False
    
    def is_whitelisted(self, filepath: str, whitelist: List[str]) -> bool:
        """檢查是否在白名單中"""
        if not whitelist:
            return False
        path = Path(filepath)
        for pattern in whitelist:
            if fnmatch.fnmatch(str(path), pattern):
                return True
        return False
    
    def is_docstring(self, filepath: str, line_no: int) -> bool:
        """檢查是否為模塊、類或函數(shù)的docstring"""
        try:
            with open(filepath, 'r', encoding='utf-8') as f:
                content = f.read()
            
            tree = ast.parse(content)
            
            # 檢查模塊級docstring
            if (isinstance(tree.body[0], ast.Expr) and 
                isinstance(tree.body[0].value, ast.Str) and 
                tree.body[0].lineno == line_no):
                return True
            
            # 檢查類和函數(shù)的docstring
            for node in ast.walk(tree):
                if (isinstance(node, (ast.FunctionDef, ast.ClassDef, ast.AsyncFunctionDef)) and
                    node.body and 
                    isinstance(node.body[0], ast.Expr) and 
                    isinstance(node.body[0].value, ast.Str) and 
                    node.body[0].lineno == line_no):
                    return True
                    
        except Exception:
            pass
            
        return False
    
    def analyze_file(self, filepath: str) -> List[Dict[str, Any]]:
        """分析單個文件中的字符串引號使用"""
        issues = []
        
        try:
            with open(filepath, 'r', encoding='utf-8') as f:
                content = f.read()
            
            # 使用tokenize進行分詞分析
            f.seek(0)
            tokens = list(tokenize.generate_tokens(f.readline))
            
            for token in tokens:
                if token.type == tokenize.STRING:
                    self.stats['total_strings'] += 1
                    string_value = token.string
                    
                    # 跳過空字符串
                    if len(string_value) <= 2:
                        continue
                    
                    # 檢查是否為單引號字符串(排除雙引號包含單引號的情況)
                    if (string_value.startswith("'") and string_value.endswith("'") and
                        not ('"' in string_value and string_value.count('"') >= 2)):
                        
                        # 檢查前綴
                        prefix = ''
                        if string_value[0] in 'rubf' or string_value.startswith(('fr', 'rf', 'br', 'rb')):
                            # 提取前綴
                            quote_start = string_value.find("'")
                            if quote_start > 0:
                                prefix = string_value[:quote_start]
                        
                        # 跳過docstring
                        if self.is_docstring(filepath, token.start[0]):
                            self.stats['skipped_strings'] += 1
                            continue
                        
                        self.stats['single_quote_strings'] += 1
                        
                        issues.append({
                            'file': filepath,
                            'line': token.start[0],
                            'column': token.start[1],
                            'original_string': string_value,
                            'suggested_string': prefix + '"' + string_value[len(prefix)+1:-1] + '"',
                            'prefix': prefix,
                            'content': string_value[len(prefix)+1:-1]
                        })
                        
        except Exception as e:
            self.stats['error_files'] += 1
            print(f"錯誤分析文件 {filepath}: {e}")
            
        return issues
    
    def replace_string_in_file(self, filepath: str, replacements: List[Dict[str, Any]]) -> int:
        """在文件中替換字符串"""
        replaced_count = 0
        
        try:
            with open(filepath, 'r', encoding='utf-8') as f:
                lines = f.readlines()
            
            # 按行號降序排序,避免替換時影響行號
            replacements.sort(key=lambda x: x['line'], reverse=True)
            
            for replacement in replacements:
                line_no = replacement['line'] - 1  # 轉(zhuǎn)換為0-based索引
                original = replacement['original_string']
                suggested = replacement['suggested_string']
                
                # 獲取當(dāng)前行內(nèi)容
                line_content = lines[line_no]
                
                # 替換字符串
                new_line = line_content.replace(original, suggested, 1)
                
                if new_line != line_content:
                    lines[line_no] = new_line
                    replaced_count += 1
                    print(f"替換: {original} -> {suggested}")
                else:
                    print(f"警告: 無法替換 {original}")
            
            # 寫回文件
            if replaced_count > 0:
                with open(filepath, 'w', encoding='utf-8') as f:
                    f.writelines(lines)
                    
        except Exception as e:
            print(f"錯誤替換文件 {filepath}: {e}")
            
        return replaced_count
    
    def process_directory(self, root_dir: str, exclude_dirs: List[str], 
                         whitelist: List[str], auto_fix: bool = False) -> None:
        """處理目錄中的所有Python文件"""
        root_path = Path(root_dir)
        
        for py_file in root_path.rglob("*.py"):
            if self.is_excluded_directory(str(py_file), exclude_dirs):
                continue
                
            if whitelist and not self.is_whitelisted(str(py_file), whitelist):
                continue
                
            self.stats['files_processed'] += 1
            print(f"\n分析文件: {py_file}")
            
            issues = self.analyze_file(str(py_file))
            
            if issues:
                self.issues.extend(issues)
                self.stats['issues_found'] += len(issues)
                
                print(f"發(fā)現(xiàn) {len(issues)} 個單引號字符串:")
                
                replacements = []
                for issue in issues:
                    print(f"  行 {issue['line']}: {issue['original_string']}")
                    
                    if auto_fix:
                        replacements.append(issue)
                    else:
                        # 交互式確認
                        response = input(f"替換為 {issue['suggested_string']}? (y/n/a): ").lower()
                        if response == 'y':
                            replacements.append(issue)
                        elif response == 'a':
                            auto_fix = True
                            replacements.append(issue)
                
                # 執(zhí)行替換
                if replacements:
                    replaced = self.replace_string_in_file(str(py_file), replacements)
                    self.stats['replaced_strings'] += replaced
                    print(f"成功替換 {replaced} 個字符串")
    
    def save_stats(self, output_file: str) -> None:
        """保存統(tǒng)計信息到JSON文件"""
        stats_data = {
            'summary': self.stats,
            'issues': self.issues
        }
        
        with open(output_file, 'w', encoding='utf-8') as f:
            json.dump(stats_data, f, indent=2, ensure_ascii=False)
        
        print(f"\n統(tǒng)計信息已保存到: {output_file}")

def main():
    parser = argparse.ArgumentParser(description='Python字符串引號規(guī)范檢查與修復(fù)工具')
    parser.add_argument('path', help='要檢查的文件或目錄路徑')
    parser.add_argument('--exclude', nargs='*', default=[], help='排除的目錄模式')
    parser.add_argument('--whitelist', nargs='*', default=[], help='白名單文件模式')
    parser.add_argument('--auto-fix', action='store_true', help='自動修復(fù)模式')
    parser.add_argument('--output', default='string_quote_stats.json', help='統(tǒng)計輸出文件')
    
    args = parser.parse_args()
    
    checker = StringQuoteChecker()
    
    if os.path.isfile(args.path):
        # 處理單個文件
        if args.whitelist and not checker.is_whitelisted(args.path, args.whitelist):
            print("文件不在白名單中")
            return
        
        issues = checker.analyze_file(args.path)
        if issues:
            replacements = []
            for issue in issues:
                print(f"行 {issue['line']}: {issue['original_string']}")
                
                if args.auto_fix:
                    replacements.append(issue)
                else:
                    response = input(f"替換為 {issue['suggested_string']}? (y/n): ").lower()
                    if response == 'y':
                        replacements.append(issue)
            
            if replacements:
                replaced = checker.replace_string_in_file(args.path, replacements)
                checker.stats['replaced_strings'] += replaced
                print(f"成功替換 {replaced} 個字符串")
    
    elif os.path.isdir(args.path):
        # 處理目錄
        checker.process_directory(args.path, args.exclude, args.whitelist, args.auto_fix)
    
    else:
        print(f"路徑不存在: {args.path}")
        return
    
    # 輸出統(tǒng)計信息
    print("\n" + "="*50)
    print("統(tǒng)計摘要:")
    for key, value in checker.stats.items():
        print(f"  {key}: {value}")
    
    # 保存詳細統(tǒng)計
    checker.save_stats(args.output)

if __name__ == "__main__":
    main()

這個Python編碼規(guī)范自動修復(fù)程序展示了如何結(jié)合多種Python標準庫來構(gòu)建一個實用的代碼質(zhì)量工具。通過智能的字符串識別、安全的替換機制和詳細的統(tǒng)計報告,它能夠在保證代碼安全的前提下,有效地統(tǒng)一代碼風(fēng)格。該工具的設(shè)計思路和技術(shù)實現(xiàn)也可以為其他代碼質(zhì)量工具的開發(fā)提供參考。

程序的模塊化設(shè)計使得它易于擴展,未來可以添加更多的代碼規(guī)范檢查功能,如行長度檢查、導(dǎo)入順序整理等,成為一個全面的Python代碼質(zhì)量工具套件。

程序架構(gòu)設(shè)計

1. 核心組件

StringQuoteChecker類是整個程序的核心,負責(zé):

  • 文件遍歷和過濾
  • 字符串語法分析
  • 問題檢測和修復(fù)
  • 統(tǒng)計信息收集

2. 技術(shù)棧選擇

  • ast庫:用于解析Python抽象語法樹,準確識別docstring位置
  • tokenize庫:進行詞法分析,精確提取字符串token
  • argparse庫:提供友好的命令行接口
  • pathlib庫:跨平臺路徑處理

關(guān)鍵技術(shù)實現(xiàn)

1. 智能字符串識別

def analyze_file(self, filepath: str) -> List[Dict[str, Any]]:
    # 使用tokenize精確識別字符串
    tokens = list(tokenize.generate_tokens(f.readline))
    
    for token in tokens:
        if token.type == tokenize.STRING:
            # 處理帶前綴的字符串:r、u、f、b等
            prefix = ''
            if string_value[0] in 'rubf' or string_value.startswith(('fr', 'rf', 'br', 'rb')):
                quote_start = string_value.find("'")
                if quote_start > 0:
                    prefix = string_value[:quote_start]

2. Docstring智能排除

def is_docstring(self, filepath: str, line_no: int) -> bool:
    # 使用AST分析識別模塊、類、函數(shù)的docstring
    tree = ast.parse(content)
    
    # 檢查模塊級docstring
    if (isinstance(tree.body[0], ast.Expr) and 
        isinstance(tree.body[0].value, ast.Str) and 
        tree.body[0].lineno == line_no):
        return True

3. 安全的文件替換機制

def replace_string_in_file(self, filepath: str, replacements: List[Dict[str, Any]]) -> int:
    # 按行號降序排序,避免替換時影響行號
    replacements.sort(key=lambda x: x['line'], reverse=True)
    
    for replacement in replacements:
        # 精確替換,避免誤操作
        new_line = line_content.replace(original, suggested, 1)

功能特性

1. 智能過濾

  • 自動忽略docstring
  • 支持排除目錄模式匹配
  • 提供白名單機制
  • 正確處理字符串前綴

2. 安全修復(fù)

  • 交互式確認或自動修復(fù)模式
  • 替換前備份檢查
  • 詳細的替換日志

3. 全面統(tǒng)計

  • JSON格式的詳細報告
  • 處理進度跟蹤
  • 錯誤處理記錄

測試用例詳細說明

測試文件示例 (test_example.py)

'''模塊docstring - 應(yīng)該被忽略'''
# 單行單引號字符串 - 應(yīng)該被替換
single_quote = 'hello world'

# 雙引號字符串 - 應(yīng)該保持不變
double_quote = "hello world"

# 包含單引號的雙引號字符串 - 應(yīng)該保持不變
contains_single = "it's a test"

# 包含雙引號的單引號字符串 - 應(yīng)該被替換
contains_double = 'he said "hello"'

# 帶前綴的字符串
raw_string = r'raw string'
unicode_string = u'unicode string'
bytes_string = b'bytes string'
formatted_string = f'formatted {single_quote}'

class MyClass:
    '''類docstring - 應(yīng)該被忽略'''
    
    def __init__(self):
        '''方法docstring - 應(yīng)該被忽略'''
        self.message = 'instance attribute'

def my_function():
    '''函數(shù)docstring - 應(yīng)該被忽略'''
    local_var = 'local variable'
    return 'return value'

測試命令

# 交互式模式
python string_quote_checker.py test_example.py

# 自動修復(fù)模式
python string_quote_checker.py test_example.py --auto-fix

# 目錄處理模式
python string_quote_checker.py ./src --exclude "*/migrations/*" --whitelist "*.py" --output stats.json

預(yù)期輸出結(jié)果

修復(fù)后的test_example.py:

'''模塊docstring - 應(yīng)該被忽略'''
# 單行單引號字符串 - 應(yīng)該被替換
single_quote = "hello world"

# 雙引號字符串 - 應(yīng)該保持不變
double_quote = "hello world"

# 包含單引號的雙引號字符串 - 應(yīng)該保持不變
contains_single = "it's a test"

# 包含雙引號的單引號字符串 - 應(yīng)該被替換
contains_double = "he said \"hello\""

# 帶前綴的字符串
raw_string = r"raw string"
unicode_string = u"unicode string"
bytes_string = b"bytes string"
formatted_string = f"formatted {single_quote}"

class MyClass:
    '''類docstring - 應(yīng)該被忽略'''
    
    def __init__(self):
        '''方法docstring - 應(yīng)該被忽略'''
        self.message = "instance attribute"

def my_function():
    '''函數(shù)docstring - 應(yīng)該被忽略'''
    local_var = "local variable"
    return "return value"

統(tǒng)計輸出示例 (stats.json)

{
  "summary": {
    "files_processed": 1,
    "total_strings": 15,
    "single_quote_strings": 8,
    "replaced_strings": 6,
    "skipped_strings": 3,
    "error_files": 0,
    "issues_found": 6
  },
  "issues": [
    {
      "file": "test_example.py",
      "line": 3,
      "column": 16,
      "original_string": "'hello world'",
      "suggested_string": "\"hello world\"",
      "prefix": "",
      "content": "hello world"
    }
  ]
}

技術(shù)挑戰(zhàn)與解決方案

1. 字符串前綴處理

挑戰(zhàn):Python支持多種字符串前綴(r, u, f, b等),需要正確識別和保留。

解決方案:通過分析字符串開始部分,提取前綴并確保在替換時正確保留。

2. Docstring準確識別

挑戰(zhàn):需要區(qū)分普通字符串和docstring。

解決方案:結(jié)合AST分析和行號定位,精確識別模塊、類、函數(shù)級別的docstring。

3. 安全替換機制

挑戰(zhàn):避免在替換過程中破壞代碼結(jié)構(gòu)。

解決方案:使用精確的字符串替換,按行號降序處理,避免行號變化影響。

應(yīng)用場景

代碼規(guī)范統(tǒng)一:在大型項目中統(tǒng)一字符串引號風(fēng)格

代碼審查:在CI/CD流程中自動檢查代碼規(guī)范

遺留代碼遷移:幫助遷移舊代碼到新的編碼標準

教學(xué)工具:幫助學(xué)生理解Python編碼規(guī)范

到此這篇關(guān)于基于Python實現(xiàn)字符串規(guī)范檢查與修復(fù)程序的文章就介紹到這了,更多相關(guān)Python字符串規(guī)范檢查與修復(fù)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • python子線程如何有序執(zhí)行

    python子線程如何有序執(zhí)行

    最近在寫一個項目,需要用到子線程,那么python子線程如何有序執(zhí)行,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-05-05
  • Python?matplotlib底層原理解析

    Python?matplotlib底層原理解析

    這篇文章主要介紹了Python?matplotlib底層原理,下面文章圍繞Python?matplotlib底層原理的相關(guān)資料展開詳細內(nèi)容,具有一定的參考價值,需要的朋友可以參考下
    2021-12-12
  • python游戲開發(fā)之視頻轉(zhuǎn)彩色字符動畫

    python游戲開發(fā)之視頻轉(zhuǎn)彩色字符動畫

    這篇文章主要為大家詳細介紹了python游戲開發(fā)之視頻轉(zhuǎn)彩色字符動畫,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-04-04
  • PyInstaller打包selenium-wire過程中常見問題和解決指南

    PyInstaller打包selenium-wire過程中常見問題和解決指南

    常用的打包工具 PyInstaller 能將 Python 項目打包成單個可執(zhí)行文件,但也會因為兼容性問題和路徑管理而出現(xiàn)各種運行錯誤,本指南總結(jié)了打包過程中常見問題和解決方案,大家可以根據(jù)需要進行選擇
    2025-04-04
  • PyQt5實現(xiàn)進度條與定時器及子線程同步關(guān)聯(lián)

    PyQt5實現(xiàn)進度條與定時器及子線程同步關(guān)聯(lián)

    這篇文章主要為大家詳細介紹了PyQt5如何實現(xiàn)進度條與定時器及子線程的同步關(guān)聯(lián),文中的示例代碼講解詳細,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2023-01-01
  • Python基于自然語言處理開發(fā)文本摘要系統(tǒng)

    Python基于自然語言處理開發(fā)文本摘要系統(tǒng)

    自然語言處理(NLP)是人工智能領(lǐng)域中一個重要的研究方向,而文本摘要作為NLP的一個重要應(yīng)用,在信息爆炸的時代具有重要意義,下面我們來看看如何開發(fā)一個基于Python的文本摘要系統(tǒng)吧
    2025-04-04
  • 使用Python-UIAutomation搞定Windows桌面自動化的完全指南

    使用Python-UIAutomation搞定Windows桌面自動化的完全指南

    還在為重復(fù)點擊Windows應(yīng)用而煩惱嗎?Python-UIAutomation-for-Windows正是你需要的解決方案,本文給大家詳細介紹了使用Python-UIAutomation搞定Windows桌面自動化的完全指南,需要的朋友可以參考下
    2026-03-03
  • python中的閉包函數(shù)

    python中的閉包函數(shù)

    這篇文章主要介紹了python中的閉包函數(shù),非常不錯,具有參考借鑒價值,需要的朋友可以參考下
    2018-02-02
  • python 提取html文本的方法

    python 提取html文本的方法

    在解決自然語言處理問題時,有時你需要獲得大量的文本集。互聯(lián)網(wǎng)是文本的最大來源,但是從任意HTML頁面提取文本是一項艱巨而痛苦的任務(wù)。本文將講述python高效提取html文本的方法
    2021-05-05
  • Python爬蟲實例爬取網(wǎng)站搞笑段子

    Python爬蟲實例爬取網(wǎng)站搞笑段子

    這篇文章主要介紹了Python爬蟲實例爬取網(wǎng)站搞笑段子,具有一定參考價值,看完了代碼不妨看看段子,希望大家每天開心。
    2017-11-11

最新評論

钟山县| 秭归县| 和林格尔县| 黄陵县| 楚雄市| 康乐县| 宁明县| 天门市| 海丰县| 康乐县| 雅安市| 桦南县| 蒙自县| 安顺市| 宜州市| 柘城县| 凤城市| 垦利县| 尼勒克县| 东乌珠穆沁旗| 博罗县| 昌都县| 根河市| 高邑县| 高台县| 伊通| 庄浪县| 剑阁县| 奉节县| 托克托县| 新疆| 铅山县| 保山市| 会东县| 峨边| 腾冲县| 大悟县| 八宿县| 德清县| 石棉县| 清原|