Меню

Проверка текста питон на ошибки

Даже очень грамотный человек может сделать опечатку в слове или допустить нелепую ошибку. Этот факт не всегда остаётся замеченным при перепроверке. Использование специализированных инструментов может обеспечить корректность текстов без прямого участия человека.

Рассмотрим вопрос применения модуля Python pyenchant для обнаружения ошибок в словах и возможность их исправления.

При подготовке различной текстовой документации, договоров, отчётов и т.д. важно соблюдать правописание. Используемые в настоящее время программные средства, в частности MS Office Word, подсвечивают слова, в которых допущены ошибки. Это очень удобно и, что немаловажно, наглядно.

Но нам может понадобиться автоматизировать обнаружение ошибок в текстах при отсутствии упомянутых выше программных средств. Либо, при их наличии, делать это, не открывая документ/множество документов. Или же искомый текст может быть попросту очень длинным, его проверка займёт много времени.

На помощь приходят небезызвестный язык программирования Python и модуль pyenchant, который не только позволяет проверять правописание слов, но и предлагает варианты исправления.

Для установки модуля используется стандартная команда:

pip install pyenchant

Код для проверки правописания слова довольно прост:

import enchant # при импроте пишем именно enchant (не pyenchant)
dictionary = enchant.Dict(«en_US»)
print(dictionary.check(«driver»))

Вывод: True

Намеренно допустим ошибку в проверяемом слове:

print(dictionary.check(«draiver»))

Вывод: False

Мы можем вывести список возможных исправлений слова:

print(dictionary.suggest(u»draiver»))

Вывод: [‘driver’, ‘drainer’, ‘Rivera’]

Читатель скорее всего заинтересуется, предоставляет ли модуль возможность проверять правописание слов русского языка, и ответ – да. Однако, по умолчанию это недоступно, нам нужен словарь. Он может быть найден, например, в пакете LibreOffice по пути его установки:

«…LibreOfficeshareextensionsdict-ru»

Здесь нам нужны два файла: «ru_RU.aff» и «ru_RU.dic». Их необходимо разместить в папке модуля enchant, где хранятся словари для других языков по пути

C:…PythonPython36site-packagesenchantdatamingw64shareenchanthunspell»

Теперь, при создании объекта Dict достаточно передать строку «ru_RU», и мы сможем работать со словами русского языка.

Вернёмся к нашему примеру с ошибочно написанным словом driver. При помощи метода suggest() мы получили список возможных исправлений, и вручную мы конечно же легко сможем выбрать нужный вариант.

Но что, если мы хотим автоматизировать и этот процесс?

Давайте использовать модуль Python difflib, который позволяет сравнивать строковые последовательности. Попробуем выбрать из списка слово «driver»:

import enchant
import difflib

woi = «draiver»
sim = dict()

dictionary = enchant.Dict(«en_US»)
suggestions = set(dictionary.suggest(woi))

for word in suggestions:
measure = difflib.SequenceMatcher(None, woi, word).ratio()
sim[measure] = word

print(«Correct word is:», sim[max(sim.keys())])

Немного прокомментируем код. В словаре sim будут храниться значения степеней сходства (диапазон от 0 до 1) предложенных методом suggest() класса Dict слов с искомым словом («draiver»). Данные значения мы получаем в цикле при вызове метода ratio() класса SequenceMatcher и записываем в словарь. В конце получаем слово, которое максимально близко к проверяемому.

Вывод: Correct word is driver

Выше мы работали с отдельными словами, но будет полезно разобраться, как работать с целыми блоками текста. Для этой задачи нужно использовать класс SpellChecker:

from enchant.checker import SpellChecker

checker = SpellChecker(«en_US»)
checker.set_text(«I have got a new kar and it is ameizing.»)
print([i.word for i in checker])

Вывод: [‘kar’, ‘ameizing’]

Как видно, это не сложнее работы с отдельными словами. Кроме того, класс SpellChecker предоставляет возможность использовать фильтры, которые будут игнорировать особые последовательности, не являющиеся ошибочными, например, адрес электронной почты. Для этого необходимо импортировать класс или классы фильтров, если их несколько, и передать список фильтров параметру filters классу SpellChecker:

from enchant.checker import SpellChecker
from enchant.tokenize import EmailFilter, URLFilter

checker_with_filters = SpellChecker(«en_US», filters=[EmailFilter])
checker_with_filters.set_text(«Hi! My neim is John and thiz is my email: [email protected]»)
print([i.word for i in checker_with_filters])

Вывод: [‘neim’, ‘thiz’]

Как видно, адрес электронной почты не был выведен в качестве последовательности, содержащей ошибки в правописании.

Таким образом, комбинируя возможности модулей enchant и difflib, мы можем получить действительно мощный инструмент, позволяющий не только обнаруживать ошибки, но и подбирать варианты исправления с довольно высокой точностью, а также вносить эти исправления в текст.

For any type of text processing or analysis, checking the spelling of the word is one of the basic requirements. This article discusses various ways that you can check the spellings of the words and also can correct the spelling of the respective word.
 

Using textblob library

First, you need to install the library textblob using pip in command prompt. 

pip install textblob

You can also install this library in Jupyter Notebook as: 
 

Python3

import sys

!{sys.executable} - m pip install textblob

  
Program for Spelling checker – 
 

Python3

from textblob import TextBlob

a = "cmputr"          

print("original text: "+str(a))

b = TextBlob(a)

print("corrected text: "+str(b.correct()))

Output: 
 

original text: cmputr
corrected text: computer


Using pyspellchecker library

You can install this library as below:
Using pip: 

pip install pyspellchecker


In Jupyter Notebook: 
 

Python3

import sys

!{sys.executable} - m pip install pyspellchecker

  
Spelling Checker program using pyspellchecker – 
 

Python3

from spellchecker import SpellChecker

spell = SpellChecker()

misspelled = spell.unknown(["cmputr", "watr", "study", "wrte"])

for word in misspelled:

    print(spell.correction(word))

    print(spell.candidates(word))

Output: 
 

computer
{'caput', 'caputs', 'compute', 'computor', 'impute', 'computer'}
water
{'water', 'watt', 'warr', 'wart', 'war', 'wath', 'wat'}
write
{'wroe', 'arte', 'wre', 'rte', 'wrote', 'write'}


Using JamSpell

To achieve the best quality while making spelling corrections dictionary-based methods are not enough. You need to consider the word surroundings. JamSpell is a python spell checking library based on a language model. It makes different corrections for a different context.

1) Install swig3

apt-get install swig3.0   # for linux
brew install swig@3       # for mac

2) Install jamspell

pip install jamspell

3) Download a language model for your language

Python3

corrector = jamspell.TSpellCorrector()

corrector.LoadLangModel('Downloads/en_model.bin')

print(corrector.FixFragment('I am the begt spell cherken!'))

print(corrector.GetCandidates(['i', 'am', 'the', 'begt', 'spell', 'cherken'], 3))

print(corrector.GetCandidates(['i', 'am', 'the', 'begt', 'spell', 'cherken'], 5))

Output:

u'I am the best spell checker!'
(u'best', u'beat', u'belt', u'bet', u'bent')
(u'checker', u'chicken', u'checked', u'wherein', u'coherent', ...)

For any type of text processing or analysis, checking the spelling of the word is one of the basic requirements. This article discusses various ways that you can check the spellings of the words and also can correct the spelling of the respective word.
 

Using textblob library

First, you need to install the library textblob using pip in command prompt. 

pip install textblob

You can also install this library in Jupyter Notebook as: 
 

Python3

import sys

!{sys.executable} - m pip install textblob

  
Program for Spelling checker – 
 

Python3

from textblob import TextBlob

a = "cmputr"          

print("original text: "+str(a))

b = TextBlob(a)

print("corrected text: "+str(b.correct()))

Output: 
 

original text: cmputr
corrected text: computer


Using pyspellchecker library

You can install this library as below:
Using pip: 

pip install pyspellchecker


In Jupyter Notebook: 
 

Python3

import sys

!{sys.executable} - m pip install pyspellchecker

  
Spelling Checker program using pyspellchecker – 
 

Python3

from spellchecker import SpellChecker

spell = SpellChecker()

misspelled = spell.unknown(["cmputr", "watr", "study", "wrte"])

for word in misspelled:

    print(spell.correction(word))

    print(spell.candidates(word))

Output: 
 

computer
{'caput', 'caputs', 'compute', 'computor', 'impute', 'computer'}
water
{'water', 'watt', 'warr', 'wart', 'war', 'wath', 'wat'}
write
{'wroe', 'arte', 'wre', 'rte', 'wrote', 'write'}


Using JamSpell

To achieve the best quality while making spelling corrections dictionary-based methods are not enough. You need to consider the word surroundings. JamSpell is a python spell checking library based on a language model. It makes different corrections for a different context.

1) Install swig3

apt-get install swig3.0   # for linux
brew install swig@3       # for mac

2) Install jamspell

pip install jamspell

3) Download a language model for your language

Python3

corrector = jamspell.TSpellCorrector()

corrector.LoadLangModel('Downloads/en_model.bin')

print(corrector.FixFragment('I am the begt spell cherken!'))

print(corrector.GetCandidates(['i', 'am', 'the', 'begt', 'spell', 'cherken'], 3))

print(corrector.GetCandidates(['i', 'am', 'the', 'begt', 'spell', 'cherken'], 5))

Output:

u'I am the best spell checker!'
(u'best', u'beat', u'belt', u'bet', u'bent')
(u'checker', u'chicken', u'checked', u'wherein', u'coherent', ...)

A spell checker in Python is a software feature that checks for misspellings in a text. Spell checking features are often embedded in software or services, such as a word processor, email client, electronic dictionary or search engine.


Building a spell checker in Python

Let’s get started with building our spelling checker tool!

1. Importing Modules

We’ll build our spell checking tool with two different modules:

  • spellchecker module
  • textblob module

Let’s start by installing and importing them one by one.

For building up a spell checker in python, we need to import the spellchecker module. If you do not have the module, you can install the same using the pip package manager.

C:UsersAdmin>pip install spellchecker

You can also install the textblob module in the same way

C:UsersAdmin>pip install textblob

2. Spell Check using textblob module

TextBlob in the python programming language is a python library for processing textual data. It provides a simple API for diving into common natural language processing tasks such as part of speech tagging, noun phrase extraction, sentiment analysis, classification, translation, and more.

correct() function: The most straightforward way to correct input text is to use the correct() method.

from textblob import TextBlob
#Type in the incorrect spelling
a = "eies"
print("original text: "+str(a))
b = TextBlob(a)
#Obtain corrected spelling as an output
print("corrected text: "+str(b.correct()))

Output:

original text: eies
corrected text: eyes

3. Spell Check using spellchecker Module

Let’s see how the spellchecker module works to correct sentence errors!

#import spellchecker library
from spellchecker import SpellChecker

#create a variable spell and instance as spellchecker()
spell=SpellChecker()
'''Create a while loop under this loop you need to create a variable called a word and make this variable that takes the real-time inputs from the user.'''

while True:
    w=input('Enter any word of your choice:')
    w=w.lower()
'''if the word that presents in the spellchecker dictionary, It
will print “you spelled correctly" Else you need to find the best spelling for that word'''
    if w in spell:
        print("'{}' is spelled correctly!".format(w))
    else:
        correctwords=spell.correction(w)
        print("The best suggestion for '{}' is '{}'".format(w,correctwords))
Enter any word of your choice:gogle
The best suggestion for 'gogle' is 'google'

The spellchecker instance will be called multiple times in this program. It holds a large number of words. In case you type any misspelled words if it is not in the spellchecker dictionary it will correct it down. So this is the important thing that you know about this library.

Conclusion

This was in brief on how you can build your own spell checker using Python programming language with is easy to code, learn and understand in a very fewer line of code.

I’m fairly new to Python and NLTK. I am busy with an application that can perform spell checks (replaces an incorrectly spelled word with the correct one).
I’m currently using the Enchant library on Python 2.7, PyEnchant and the NLTK library. The code below is a class that handles the correction/replacement.

from nltk.metrics import edit_distance

class SpellingReplacer:
    def __init__(self, dict_name='en_GB', max_dist=2):
        self.spell_dict = enchant.Dict(dict_name)
        self.max_dist = 2

    def replace(self, word):
        if self.spell_dict.check(word):
            return word
        suggestions = self.spell_dict.suggest(word)

        if suggestions and edit_distance(word, suggestions[0]) <= self.max_dist:
            return suggestions[0]
        else:
            return word

I have written a function that takes in a list of words and executes replace() on each word and then returns a list of those words, but spelled correctly.

def spell_check(word_list):
    checked_list = []
    for item in word_list:
        replacer = SpellingReplacer()
        r = replacer.replace(item)
        checked_list.append(r)
    return checked_list

>>> word_list = ['car', 'colour']
>>> spell_check(words)
['car', 'color']

Now, I don’t really like this because it isn’t very accurate and I’m looking for a way to achieve spelling checks and replacements on words. I also need something that can pick up spelling mistakes like «caaaar»? Are there better ways to perform spelling checks out there? If so, what are they? How does Google do it? Because their spelling suggester is very good.

Any suggestions?

User's user avatar

User

1,14810 silver badges29 bronze badges

asked Dec 18, 2012 at 7:18

Mike Barnes's user avatar

Mike BarnesMike Barnes

4,11718 gold badges39 silver badges64 bronze badges

You can use the autocorrect lib to spell check in python.
Example Usage:

from autocorrect import Speller

spell = Speller(lang='en')

print(spell('caaaar'))
print(spell('mussage'))
print(spell('survice'))
print(spell('hte'))

Result:

caesar
message
service
the

Sunil Garg's user avatar

Sunil Garg

13.8k24 gold badges126 silver badges177 bronze badges

answered Jan 16, 2018 at 11:48

Rakesh's user avatar

5

I’d recommend starting by carefully reading this post by Peter Norvig. (I had to something similar and I found it extremely useful.)

The following function, in particular has the ideas that you now need to make your spell checker more sophisticated: splitting, deleting, transposing, and inserting the irregular words to ‘correct’ them.

def edits1(word):
   splits     = [(word[:i], word[i:]) for i in range(len(word) + 1)]
   deletes    = [a + b[1:] for a, b in splits if b]
   transposes = [a + b[1] + b[0] + b[2:] for a, b in splits if len(b)>1]
   replaces   = [a + c + b[1:] for a, b in splits for c in alphabet if b]
   inserts    = [a + c + b     for a, b in splits for c in alphabet]
   return set(deletes + transposes + replaces + inserts)

Note: The above is one snippet from Norvig’s spelling corrector

And the good news is that you can incrementally add to and keep improving your spell-checker.

Hope that helps.

answered Dec 18, 2012 at 17:13

Ram Narasimhan's user avatar

Ram NarasimhanRam Narasimhan

22.2k5 gold badges48 silver badges54 bronze badges

1

The best way for spell checking in python is by: SymSpell, Bk-Tree or Peter Novig’s method.

The fastest one is SymSpell.

This is Method1: Reference link pyspellchecker

This library is based on Peter Norvig’s implementation.

pip install pyspellchecker

from spellchecker import SpellChecker

spell = SpellChecker()

# find those words that may be misspelled
misspelled = spell.unknown(['something', 'is', 'hapenning', 'here'])

for word in misspelled:
    # Get the one `most likely` answer
    print(spell.correction(word))

    # Get a list of `likely` options
    print(spell.candidates(word))

Method2: SymSpell Python

pip install -U symspellpy

answered Feb 17, 2019 at 18:24

Shaurya Uppal's user avatar

2

Maybe it is too late, but I am answering for future searches.
TO perform spelling mistake correction, you first need to make sure the word is not absurd or from slang like, caaaar, amazzzing etc. with repeated alphabets. So, we first need to get rid of these alphabets. As we know in English language words usually have a maximum of 2 repeated alphabets, e.g., hello., so we remove the extra repetitions from the words first and then check them for spelling.
For removing the extra alphabets, you can use Regular Expression module in Python.

Once this is done use Pyspellchecker library from Python for correcting spellings.

For implementation visit this link: https://rustyonrampage.github.io/text-mining/2017/11/28/spelling-correction-with-python-and-nltk.html

answered Apr 3, 2019 at 10:10

Rishabh Sahrawat's user avatar

2

Try jamspell — it works pretty well for automatic spelling correction:

import jamspell

corrector = jamspell.TSpellCorrector()
corrector.LoadLangModel('en.bin')

corrector.FixFragment('Some sentnec with error')
# u'Some sentence with error'

corrector.GetCandidates(['Some', 'sentnec', 'with', 'error'], 1)
# ('sentence', 'senate', 'scented', 'sentinel')

jupiterbjy's user avatar

jupiterbjy

2,6671 gold badge10 silver badges27 bronze badges

answered Aug 28, 2020 at 23:00

Fippo's user avatar

FippoFippo

511 silver badge5 bronze badges

2

IN TERMINAL

pip install gingerit

FOR CODE

from gingerit.gingerit import GingerIt
text = input("Enter text to be corrected")
result = GingerIt().parse(text)
corrections = result['corrections']
correctText = result['result']

print("Correct Text:",correctText)
print()
print("CORRECTIONS")
for d in corrections:
  print("________________")  
  print("Previous:",d['text'])  
  print("Correction:",d['correct'])   
  print("`Definiton`:",d['definition'])
 

answered Mar 28, 2021 at 16:21

pouya barari's user avatar

1

You can also try:

pip install textblob

from textblob import TextBlob
txt="machne learnig"
b = TextBlob(txt)
print("after spell correction: "+str(b.correct()))

after spell correction: machine learning

answered Nov 30, 2021 at 2:47

Mayur Patil's user avatar

Mayur PatilMayur Patil

1392 silver badges5 bronze badges

2

spell corrector->

you need to import a corpus on to your desktop if you store elsewhere change the path in the code i have added a few graphics as well using tkinter and this is only to tackle non word errors!!

def min_edit_dist(word1,word2):
    len_1=len(word1)
    len_2=len(word2)
    x = [[0]*(len_2+1) for _ in range(len_1+1)]#the matrix whose last element ->edit distance
    for i in range(0,len_1+1):  
        #initialization of base case values
        x[i][0]=i
        for j in range(0,len_2+1):
            x[0][j]=j
    for i in range (1,len_1+1):
        for j in range(1,len_2+1):
            if word1[i-1]==word2[j-1]:
                x[i][j] = x[i-1][j-1]
            else :
                x[i][j]= min(x[i][j-1],x[i-1][j],x[i-1][j-1])+1
    return x[i][j]
from Tkinter import *


def retrieve_text():
    global word1
    word1=(app_entry.get())
    path="C:Documents and SettingsOwnerDesktopDictionary.txt"
    ffile=open(path,'r')
    lines=ffile.readlines()
    distance_list=[]
    print "Suggestions coming right up count till 10"
    for i in range(0,58109):
        dist=min_edit_dist(word1,lines[i])
        distance_list.append(dist)
    for j in range(0,58109):
        if distance_list[j]<=2:
            print lines[j]
            print" "   
    ffile.close()
if __name__ == "__main__":
    app_win = Tk()
    app_win.title("spell")
    app_label = Label(app_win, text="Enter the incorrect word")
    app_label.pack()
    app_entry = Entry(app_win)
    app_entry.pack()
    app_button = Button(app_win, text="Get Suggestions", command=retrieve_text)
    app_button.pack()
    # Initialize GUI loop
    app_win.mainloop()

pyspellchecker is the one of the best solutions for this problem. pyspellchecker library is based on Peter Norvig’s blog post.
It uses a Levenshtein Distance algorithm to find permutations within an edit distance of 2 from the original word.
There are two ways to install this library. The official document highly recommends using the pipev package.

  • install using pip
pip install pyspellchecker
  • install from source
git clone https://github.com/barrust/pyspellchecker.git
cd pyspellchecker
python setup.py install

the following code is the example provided from the documentation

from spellchecker import SpellChecker

spell = SpellChecker()

# find those words that may be misspelled
misspelled = spell.unknown(['something', 'is', 'hapenning', 'here'])

for word in misspelled:
    # Get the one `most likely` answer
    print(spell.correction(word))

    # Get a list of `likely` options
    print(spell.candidates(word))

answered Sep 10, 2020 at 15:30

Sabesan's user avatar

SabesanSabesan

5941 gold badge9 silver badges16 bronze badges

from autocorrect import spell
for this you need to install, prefer anaconda and it only works for words, not sentences so that’s a limitation u gonna face.

from autocorrect import spell
print(spell('intrerpreter'))
# output: interpreter

Ketan's user avatar

Ketan

131 silver badge3 bronze badges

answered Dec 28, 2018 at 11:17

Saurabh Tripathi's user avatar

1

pip install scuse

from scuse import scuse

obj = scuse()

checkedspell = obj.wordf("spelling you want to check")

print(checkedspell)

answered Sep 7, 2022 at 7:05

mrithul e's user avatar

answered Mar 12, 2020 at 14:02

Nabin's user avatar

NabinNabin

11k8 gold badges64 silver badges98 bronze badges

Autocorrect

build
Downloads
Average time to resolve an issue
Code style: black

Spelling corrector in python. Currently supports English, Polish, Turkish, Russian, Ukrainian, Czech, Portuguese, Greek, Italian, Vietnamese, French and Spanish, but you can easily add new languages.

Based on: https://github.com/phatpiglet/autocorrect and Peter Norvig’s spelling corrector.

Installation

Examples

>>> from autocorrect import Speller
>>> spell = Speller()
>>> spell("I'm not sleapy and tehre is no place I'm giong to.")
"I'm not sleepy and there is no place I'm going to."

>>> spell = Speller('pl')
>>> spell('ptaaki latatją kluczmm')
'ptaki latają kluczem'

Speed

%timeit spell("I'm not sleapy and tehre is no place I'm giong to.")
373 µs ± 2.09 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
%timeit spell("There is no comin to consiousnes without pain.")
150 ms ± 2.02 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

As you see, for some words correction can take ~200ms. If speed is important for your use case (e.g. chatbot) you may want to use option ‘fast’:

spell = Speller(fast=True)
%timeit spell("There is no comin to consiousnes without pain.")
344 µs ± 2.23 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

Now, the correction should always work in microseconds, but words with double typos (like ‘consiousnes’) won’t be corrected.

OCR

When cleaning up OCR, replacements are the large majority of errors. If this is the case, you may want to use the option ‘only_replacements’:

spell = Speller(only_replacements=True)

Custom word sets

If you wish to use your own set of words for autocorrection, you can pass an nlp_data argument:

spell = Speller(nlp_data=your_word_frequency_dict)

Where your_word_frequency_dict is a dictionary which maps words to their average frequencies in your text. If you want to change the default word set only a bit, you can just edit spell.nlp_data parameter, after spell was initialized.

Adding new languages

First, define special letters, by adding entries in word_regexes and alphabets dicts in autocorrect/constants.py.

Now, you need a bunch of text. Easiest way is to download wikipedia.
For example for Russian you would go to:
https://dumps.wikimedia.org/ruwiki/latest/
and download ruwiki-latest-pages-articles.xml.bz2

bzip2 -d ruiwiki-latest-pages-articles.xml.bz2

After that:

First, edit the autocorrect.constants dictionaries in order to accommodate regexes and dictionaries for your language.

Then:

>>> from autocorrect.word_count import count_words
>>> count_words('ruwiki-latest-pages-articles.xml', 'ru')
tar -zcvf autocorrect/data/ru.tar.gz word_count.json

For the correction to work well, you need to cut out rarely used words. First, in test_all.py, write test words for your language, and add them to optional_language_tests the same way as it’s done for other languages. It’s good to have at least 30 words. Now run:

python test_all.py find_threshold ru

and see which threshold value has the least badly corrected words. After that, manually delete all the words with less occurences than the threshold value you found, from the file in hi.tar.gz (it’s already sorted so it should be easy).

To distribute this language support to others, you will need to upload your tar.gz file to IPFS (for example with Pinata, which will pin this file so it doesn’t disappear), and then add it’s path to ipfs_paths in constants.py. (tip: first put this file inside the folder, and upload the folder to IPFS, for the downloaded file to have the correct filename)

Good luck!

Рассмотрим популярные инструменты для анализа кода Python и подробно расскажем об их специфике и основных принципах работы.

Инструменты для анализа кода Python. Часть 1

Автор: Валерий Шагур, teacher assistance на курсе Программирование на Python

Высокая стоимость ошибок в программных продуктах предъявляет повышенные
требования к качеству кода. Каким критериям должен соответствовать хороший код?
Отсутствие ошибок, расширяемость, поддерживаемость, читаемость и наличие документации. Недостаточное внимание к любому из этих критериев может привести к появлению новых ошибок или снизить вероятность обнаружения уже существующих. Небрежно написанный или чересчур запутанный код, отсутствие документации напрямую влияют на время исправления найденного бага, ведь разработчику приходится заново вникать в код. Даже такие, казалось бы, незначительные вещи как неправильные имена переменных или отсутствие форматирования могут сильно влиять на читаемость и понимание кода.

Командная работа над проектом еще больше повышает требования к качеству кода, поэтому важным условием продуктивной работы команды становится описание формальных требований к написанию кода. Это могут быть соглашения, принятые в языке программирования, на котором ведется разработка, или собственное (внутрикорпоративное) руководство по стилю. Выработанные требования к оформлению кода не исключают появления «разночтений» среди разработчиков и временных затрат на их обсуждение. Кроме этого, соблюдение выработанных требований ложится на плечи программистов в виде дополнительной нагрузки. Все это привело к появлению инструментов для проверки кода на наличие стилистических и логических ошибок. О таких инструментах для языка программирования Python мы и поговорим в этой статье.

Анализаторы и автоматическое форматирование кода

Весь инструментарий, доступный разработчикам Python, можно условно разделить на две группы по способу реагирования на ошибки. Первая группа сообщает о найденных ошибках, перекладывая задачу по их исправлению на программиста. Вторая — предлагает пользователю вариант исправленного кода или автоматически вносит изменения.

И первая, и вторая группы включают в себя как простые утилиты командной строки для решения узкоспециализированных задач (например, проверка docstring или сортировка импортов), так и богатые по возможностям библиотеки, объединяющие в себе более простые утилиты. Средства анализа кода из первой группы принято называть линтерами (linter). Название происходит от lint — статического анализатора для языка программирования Си и со временем ставшего нарицательным. Программы второй группы называют форматировщиками (formatter).

Даже при поверхностном сравнении этих групп видны особенности работы с ними. При применении линтеров программисту, во-первых, необходимо писать код с оглядкой, дабы позже не исправлять найденные ошибки. И во вторых, принимать решение по поводу обнаруженных ошибок — какие требуют исправления, а какие можно проигнорировать. Форматировщики, напротив, автоматизируют процесс исправления ошибок, оставляя программисту возможность осуществлять контроль.

Часть 1

  • pycodestyle
  • pydocstyle
  • pyflakes
  • pylint
  • vulture

Часть 2

  • flake8
  • prospector
  • pylama
  • autopep8
  • yapf
  • black

Соглашения принятые в статье и общие замечания

Прежде чем приступить к обзору программ, мы хотели бы обратить ваше внимание на несколько важных моментов.

Версия Python: во всех примерах, приведенных в статье, будет использоваться третья версия языка программирования Python.

Установка всех программ в обзоре практически однотипна и сводится к использованию пакетного менеджера pip.

$ python3.6 -m pip install --upgrade <package_name>

Некоторые из библиотек имеют готовые бинарные пакеты в репозиториях дистрибутивов linux или возможность установки с использованием git. Тем не менее для большей определенности и возможности повторения примеров из статьи, установка будет производится с помощью pip.

Об ошибках: стоит упомянуть, что говоря об ошибках, обнаруживаемых анализаторами кода, как правило, имеют в виду два типа ошибок. К первому относятся ошибки стиля (неправильные отступы, длинные строки), ко второму — ошибки в логике программы и ошибки синтаксиса языка программирования (опечатки при написании названий стандартных функций, неиспользуемые импорты, дублирование кода). Существуют и другие виды ошибок, например — оставленные в коде пароли или высокая цикломатическая сложность.

Тестовый скрипт: для примеров использования программ мы создали простенький по содержанию файл example.py. Мы сознательно не стали делать его более разнообразным по наличию в нем ошибок. Во-первых, добавление листингов с выводом некоторых анализаторов в таком случае сильно “раздуло” бы статью. Во-вторых, у нас не было цели детально показать различия в “отлове” тех или иных ошибок для каждой из утилит.

Содержание файла example.py:

import os
import notexistmodule

def Function(num,num_two):
return num

class MyClass:
"""class MyClass """

def __init__(self,var):
self.var=var

def out(var):
print(var)


if __name__ == "__main__":
my_class = MyClass("var")
my_class.out("var")
notexistmodule.func(5)

В коде допущено несколько ошибок:

  • импорт неиспользуемого модуля os,
  • импорт не существующего модуля notexistmodule,
  • имя функции начинается с заглавной буквы,
  • лишние аргументы в определении функции,
  • отсутствие self первым аргументом в методе класса,
  • неверное форматирование.

Руководства по стилям: для тех, кто впервые сталкивается с темой оформления кода, в качестве знакомства предлагаем прочитать официальные руководства по стилю для языка Python PEP8 и PEP257. В качестве примера внутрикорпоративных соглашений можно рассмотреть Google Python Style Guide — https://github.com/google/styleguide/blob/gh-pages/pyguide.md

Pycodestyle

Pycodestyle — простая консольная утилита для анализа кода Python, а именно для проверки кода на соответствие PEP8. Один из старейших анализаторов кода, до 2016 года носил название pep8, но был переименован по просьбе создателя языка Python Гвидо ван Россума.

Запустим проверку на нашем коде:

$ python3 -m pycodestyle example.py 
example.py:4:1: E302 expected 2 blank lines, found 1
example.py:4:17: E231 missing whitespace after ','
example.py:7:1: E302 expected 2 blank lines, found 1
example.py:10:22: E231 missing whitespace after ','
example.py:11:17: E225 missing whitespace around operator

Лаконичный вывод показывает нам строки, в которых, по мнению анализатора, есть нарушение соглашений PEP8. Формат вывода прост и содержит только необходимую информацию:

<имя файла>: <номер строки> :<положение символа>: <код и короткая расшифровка ошибки>

Возможности программы по проверке соглашений ограничены: нет проверок на правильность именования, проверка документации сводится к проверки длины docstring. Тем не менее функционал программы нельзя назвать “спартанским”, он позволяет настроить необходимый уровень проверок и получить различную информацию о результатах анализа. Запуск с ключом —statistics -qq выводит статистику по ошибкам:

$ python3 -m pycodestyle --statistics -qq example.py 
1 E225 missing whitespace around operator
2 E231 missing whitespace after ','
2 E302 expected 2 blank lines, found 1

Более наглядный вывод можно получить при использовании ключа —show-source. После каждого сообщения об ошибке будет выведена строка исходного кода, в которой содержится ошибка.

$ python3 -m pycodestyle --show-source example.py 
example.py:4:1: E302 expected 2 blank lines, found 1
def Function(num,num_two):
^
example.py:4:17: E231 missing whitespace after ','
def Function(num,num_two):
^
example.py:7:1: E302 expected 2 blank lines, found 1
class MyClass:
^
example.py:10:22: E231 missing whitespace after ','
def __init__(self,var):
^
example.py:11:17: E225 missing whitespace around operator
self.var=var
^

Если есть необходимость посмотреть, какие из соглашений PEP8 были нарушены, используйте ключ — show-pep8. Программа выведет список всех проверок с выдержками из PEP8 для случаев нарушений. При обработке файлов внутри директорий предусмотрена возможность фильтрации по шаблону. Pycodestyle позволяет сохранять настройки поиска в конфигурационных файлах как глобально, так и на уровне проекта.

Pydocstyle

Утилиту pydocstyle мы уже упоминали в статье Работа с документацией в Python: поиск информации и соглашения. Pydocstyle проверяет наличие docstring у модулей, классов, функций и их соответствие официальному соглашению PEP257.

$ python3 -m pydocstyle example.py
example.py:1 at module level:
D100: Missing docstring in public module
example.py:4 in public function `Function`:
D103: Missing docstring in public function
example.py:7 in public class `MyClass`:
D400: First line should end with a period (not 's')
example.py:7 in public class `MyClass`:
D210: No whitespaces allowed surrounding docstring text
example.py:10 in public method `__init__`:
D107: Missing docstring in __init__
example.py:13 in public method `out`:
D102: Missing docstring in public method

Как мы видим из листинга, программа указала нам на отсутствие документации в определениях функции, методов класса и ошибки оформления в docstring класса. Вывод можно сделать более информативным, если использовать ключи —explain и —source при вызове программы. Функционал pydocstyle практически идентичен описанному выше для pycodestyle, различия касаются лишь названий ключей.

Pyflakes

В отличие от уже рассмотренных инструментов для анализа кода Python pyflakes не делает проверок стиля. Цель этого анализатора кода — поиск логических и синтаксических ошибок. Разработчики pyflakes сделали упор на скорость работы программы, безопасность и простоту. Несмотря на то, что данная утилита не импортирует проверяемый файл, она прекрасно справляется c поиском синтаксических ошибок и делает это быстро. С другой стороны, такой подход сильно сужает область проверок.
Функциональность pyflakes — “нулевая”, все что он умеет делать — это выводить результаты анализа в консоль:

$ python3 -m pyflakes example.py 
example.py:1: 'os' imported but unused

В нашем тестовом скрипте, он нашел только импорт не используемого модуля os. Вы можете самостоятельно поэкспериментировать с запуском программы и передачей ей в качестве параметра командной строки Python файла, содержащего синтаксические ошибки. Данная утилита имеет еще одну особенность — если вы используете обе версии Python, вам придется установить отдельные утилиты для каждой из версий.

Pylint

До сих пор мы рассматривали утилиты, которые проводили проверки на наличие либо стилистических, либо логических ошибок. Следующий в обзоре статический инструмент для анализа кода Python — Pylint, который совместил в себе обе возможности. Этот мощный, гибко настраиваемый инструмент для анализа кода Python отличается большим количеством проверок и разнообразием отчетов. Это один из самых “придирчивых” и “многословных” анализаторов кода. Анализ нашего тестового скрипта выдает весьма обширный отчет, состоящий из списка найденных в ходе анализа недочетов, статистических отчетов, представленных в виде таблиц, и общей оценки кода:

$ python3.6 -m pylint --reports=y text example.py
************* Module text
/home/ququshka77/.local/lib/python3.6/site-packages/pylint/reporters/text.py:79:22: W0212: Access to a protected member _splitstrip of a client class (protected-access)
************* Module example
example.py:4:16: C0326: Exactly one space required after comma
def Function(num,num_two):
                           ^ (bad-whitespace)
example.py:10:21: C0326: Exactly one space required after comma
    def __init__(self,var):
                             ^ (bad-whitespace)
example.py:11:16: C0326: Exactly one space required around assignment
        self.var=var
                    ^ (bad-whitespace)
example.py:1:0: C0111: Missing module docstring (missing-docstring)
example.py:2:0: E0401: Unable to import 'notexistmodule' (import-error)
example.py:4:0: C0103: Function name "Function" doesn't conform to snake_case naming style (invalid-name)
example.py:4:0: C0111: Missing function docstring (missing-docstring)
example.py:4:17: W0613: Unused argument 'num_two' (unused-argument)
example.py:13:4: C0111: Missing method docstring (missing-docstring)
example.py:13:4: E0213: Method should have "self" as first argument (no-self-argument)
example.py:7:0: R0903: Too few public methods (1/2) (too-few-public-methods)
example.py:18:4: C0103: Constant name "my_class" doesn't conform to UPPER_CASE naming style (invalid-name)
example.py:19:4: E1121: Too many positional arguments for method call (too-many-function-args)
example.py:1:0: W0611: Unused import os (unused-import)

Report
======
112 statements analysed.

Statistics by type
+----------+----------+---------------+-------------+-------------------+---------------+
|type     |number      |old number        |difference      |%documented       |%badname |
+======+======+========+========+===========+========+
|module   |2           |2                 |=               |50.00             |0.00            |
+-----------+----------+---------------+-------------+-------------------+---------------+
|class    |5           |5                 |=               |100.00            |0.00            |
+-----------+----------+---------------+-------------+-------------------+---------------+
|method   |11          |11                |=               |90.91             |0.00            |
+-----------+----------+---------------+-------------+-------------------+---------------+
|function |4           |4                 |=               |75.00             |25.00          |
+-----------+----------+---------------+-------------+-------------------+---------------+

External dependencies
::
    pylint 
      -interfaces (text)
      -reporters (text)
      | -ureports 
      |   -text_writer (text)
      -utils (text)


Raw metrics
+-------------+----------+-------+-----------+-------------+
|type        |number |%     |previous    |difference |
+=======+======+=====+=====+========+
|code        |128    |48.30 |128         |=               |
+-------------+----------+--------+-----------+------------+
|docstring   |84     |31.70 |84          |=               |
+-------------+----------+--------+-----------+------------+
|comment     |16     |6.04  |16          |=               |
+-------------+----------+--------+-----------+------------+
|empty       |37     |13.96 |37          |=               |
+-------------+----------+--------+-----------+------------+

Duplication
+-------------------------------+------+------------+-------------+
|                            |now      |previous      |difference |
+=================+=====+======+========+
|nb duplicated lines         |0        |0             |=              |
+-------------------------------+-------+------------+------------+
|percent duplicated lines    |0.000    |0.000         |=              |
+-------------------------------+-------+------------+------------+

Messages by category
+--------------+----------+-----------+-------------+
|type            |number |previous |difference |
+========+======+======+========+
|convention      |8       |8       |=               |
+--------------+----------+-----------+-------------+
|refactor        |1       |1       |=               |
+--------------+-----------+----------+-------------+
|warning         |3       |3       |=               |
+--------------+-----------+----------+-------------+
|error           |3       |3       |=               |
+--------------+-----------+----------+-------------+

% errors / warnings by module
+-----------+--------+-----------+----------+--------------+
|module   |error    |warning |refactor |convention   |
+======+=====+======+======+========+
|example  |100.00   |66.67   |100.00   |100.00       |
+-----------+---------+----------+-----------+-------------+
|text     |0.00     |33.33   |0.00     |0.00         |
+-----------+---------+----------+-----------+-------------+

Messages
+-----------------------------+----------------+
|message id                  |occurrences |
+=================+=========+
|missing-docstring           |3                 |
+-----------------------------+----------------+
|bad-whitespace              |3                 |
+------------------------------+---------------+
|invalid-name                |2                 |
+------------------------------+---------------+
|unused-import               |1                 |
+------------------------------+---------------+
|unused-argument             |1                 |
+------------------------------+---------------+
|too-many-function-args      |1                 | 
+------------------------------+---------------+
|too-few-public-methods      |1                 |
+------------------------------+---------------+
|protected-access            |1                 |
+------------------------------+---------------+
|no-self-argument            |1                 |
+------------------------------+---------------+
|import-error                |1                 |
+------------------------------+---------------+

------------------------------------------------------------------------------------------
Your code has been rated at 7.59/10 (previous run: 7.59/10, +0.00)

Программа имеет свою внутреннюю маркировку проблемных мест в коде:

[R]efactor — требуется рефакторинг,
[C]onvention — нарушено следование стилистике и соглашениям,
[W]arning — потенциальная ошибка,
[E]rror — ошибка,
[F]atal — ошибка, которая препятствует дальнейшей работе программы.

Для вывода подробного отчета мы использовали ключ командной строки —reports=y.
Более гибко настроить вывод команды позволяют разнообразные ключи командной строки. Настройки можно сохранять в файле настроек rcfile. Мы не будем приводить подробное описание ключей и настроек, для этого есть официальная документация — https://pylint.readthedocs.io/en/latest/index.html#, остановимся лишь на наиболее интересных, с нашей точки зрения, возможностях утилиты:

— Генерация файла настроек (—generate-rcfile). Позволяет не писать конфигурационный файл с нуля. В созданном rcfile содержатся все текущие настройки с подробными комментариями к ним, вам остается только отредактировать его под собственные требования.

— Отключение вывода в коде. При редактировании кода есть возможность вставить блокирующие вывод сообщений комментарии. Чтобы продемонстрировать это, в определение функции в файле примера example.py добавим строку:

# pylint: disable=unused-argument

и запустим pylint. Из результатов проверки “исчезло” сообщение:

example.py:4:17: W0613: Unused argument 'num_two' (unused-argument)

— Создание отчетов в формате json (—output-format=json). Полезно, если необходимо сохранение или дальнейшая обработка результатов работы линтера. Вы также можете создать собственный формат вывода данных.

— Параллельный запуск (-j 4). Запуск в нескольких параллельных потоках на многоядерных процессорах сокращает время проверки.

— Встроенная документация. Вызов программы с ключом —help-msg=<key> выведет справку по ключевому слову key. В качестве ключевого слова может быть код сообщения (например: E0401) или символическое имя сообщения (например: import-error). Ниже приведен листинг получения справки по ключу import-error:

$ python3.6 -m pylint --help-msg=import-error
:import-error (E0401): *Unable to import %s*
Used when pylint has been unable to import a module. This message belongs to
the imports checker.

— Система оценки сохраняет последний результат и при последующих запусках показывает изменения, что позволяет количественно оценить прогресс исправлений.

— Плагины — отличная возможность изменять поведение pylint. Их применение может оказаться полезным в случаях, когда pylint неправильно обрабатывает код и есть “ложные” срабатывания, или когда требуется отличный от стандартного формат вывода результатов.

Vulture

Vulture — небольшая утилита для поиска “мертвого” кода в программах Python. Она использует модуль ast стандартной библиотеки и создает абстрактные синтаксические деревья для всех файлов исходного кода в проекте. Далее осуществляется поиск всех объектов, которые были определены, но не используются. Vulture полезно применять для очистки и нахождения ошибок в больших базовых кодах.

Продолжение следует

Во второй части мы продолжим разговор об инструментах для анализа кода Python. Будут рассмотрены линтеры, представляющие собой наборы утилит. Также мы посмотрим, какие программы можно использовать для автоматического форматирования кода.

Еще статьи по Python

  • 26 полезных возможностей Python: букварь разработки от А до Z;
  • ТОП-15 трюков в Python 3, делающих код понятнее и быстрее;
  • Новый Python: 7 возможностей, которые вам понравятся;
  • Крупнейшая подборка Python-каналов на Youtube;
  • Изучение Python: ТОП-10 вопросов разной направленности.

0 0 голоса
Рейтинг статьи
Подписаться
Уведомить о
guest

0 комментариев
Старые
Новые Популярные
Межтекстовые Отзывы
Посмотреть все комментарии

А вот еще интересные материалы:

  • Яшка сломя голову остановился исправьте ошибки
  • Ясность цели позволяет целеустремленно добиваться намеченного исправьте ошибки
  • Ясность цели позволяет целеустремленно добиваться намеченного где ошибка
  • Проверка сетевой карты на ошибки windows 10
  • Проверка ошибок ваз 2114 на приборной панели