Skip to content

Instantly share code, notes, and snippets.

@pimiento
Last active August 29, 2015 13:57
Show Gist options
  • Save pimiento/9649115 to your computer and use it in GitHub Desktop.
Save pimiento/9649115 to your computer and use it in GitHub Desktop.
Проверяем с помощью cProfile время выполнения трёх разных способов валидации для большого количества записей
#!/usr/bin/env python2
# -*- coding: utf-8 -*-
import re
import random
import string
import cProfile
rgx = re.compile(r"^[a-zA-Z][a-zA-Z0-9.-]{0,18}[a-zA-Z0-9]$")
def rchecker(login):
return bool(rgx.match(login))
max_len = 20
def occhecker(login):
"""
Проверка корректности логина посимвольным проходом в цикле.
Для оптимизации используются числовые коды символов, а не поиск вида:
if c not in string.ascii_letters
Но интересный момент: получается медленнее!
"""
length_counter = max_len
for c in login:
o = ord(c)
if length_counter == max_len: # начинается не с латинской буквы
if not (o > 96 and o < 123) and \
not (o > 64 and o < 91): return False
if length_counter == 0: return False # превышена длина
# not a digit
# not a uppercase letter
# not a downcase letter
# not a minus or dot
if not (o > 47 and o < 58) and \
not (o > 96 and o < 123) and \
not (o > 64 and o < 91) and \
o != 45 and o != 46: return False
length_counter -= 1
if length_counter < max_len:
o = ord(c)
# был хоть один символ и последний цифра или латинская буква
if not (o > 47 and o < 58) and \
not (o > 96 and o < 123) and \
not (o > 64 and o < 91): return False
else: return True
else: return False
correct_end = string.ascii_letters + string.digits
correct_symbols = correct_end + "-."
def cchecker(login):
"""
Проверка корректности логина в цикле
"""
length_counter = max_len
for c in login:
if length_counter == max_len and c not in string.ascii_letters:
# начинается не с латинской буквы
return False
if length_counter == 0:
# превышена длина
return False
if c not in correct_symbols:
return False
length_counter -= 1
if length_counter < max_len and c in correct_end:
# был хоть один символ и последний цифра или латинская буква
return True
else:
return False
# чтоб не ставить pwgen pip-ом, здесь генератор случайных паролей/логинов
choice = random.SystemRandom().choice
randint = random.SystemRandom().randint
LowercaseLetters = string.ascii_lowercase
UpperCase = string.ascii_uppercase
Digits = string.digits
Symbols = string.punctuation
HasCaps = re.compile("[A-Z]")
HasNumerals = re.compile("[0-9]")
HasSymbols = re.compile(r"[%s]" % re.escape(Symbols))
HasAmbiguous = re.compile("[B8G6I1l|0OQDS5Z2]")
def replaceRandomChar(letter, word, pos=None):
if not pos:
pos = randint(0, len(word))
word = list(word)
word[pos] = letter
return "".join(word)
def pwgen(pw_length=20, num_pw=1, no_numerals=False, no_capitalize=False, capitalize=False,
numerals=False, no_symbols=False, symbols=False, allowed_symbols=None,
no_ambiguous=False):
global Symbols, HasSymbols
letters = LowercaseLetters
if not no_capitalize:
letters += UpperCase
if not no_numerals:
letters += Digits
if not no_symbols:
if allowed_symbols is not None:
Symbols = allowed_symbols
HasSymbols = re.compile(r"[%s]" % re.escape(Symbols))
letters += Symbols
passwds = []
while len(passwds) < int(num_pw):
passwd = "".join(choice(letters) for x in range(pw_length))
if capitalize and not HasCaps.search(passwd):
passwd = replaceRandomChar(choice(UpperCase), passwd)
if numerals and not HasNumerals.search(passwd):
passwd = replaceRandomChar(choice(Digits), passwd)
if symbols and not HasSymbols.search(passwd):
passwd = replaceRandomChar(choice(Symbols), passwd)
if no_ambiguous and HasAmbiguous.search(passwd):
continue
passwds.append(passwd)
if len(passwds) == 1:
return passwds[0]
return passwds
# нагенерируем кучу логинов корректных и не очень
logins_list = []
for variant in [
dict(num_pw=100000, capitalize=True, allowed_symbols="-."),
dict(num_pw=60000, capitalize=True, allowed_symbols="-.а-яА-Я"),
dict(num_pw=60000, capitalize=True, allowed_symbols="-.", pw_length=24),
dict(pw_length=0, num_pw=60000)]:
logins_list += pwgen(**variant)
random.shuffle(logins_list)
# замеряем скорость трёх методов
pr = cProfile.Profile()
pr.enable()
[cchecker(login) for login in logins_list] # цикл
pr.disable()
pr.print_stats()
pr.clear()
pr.enable()
[rchecker(login) for login in logins_list] # регэкспы
pr.disable()
pr.print_stats()
pr.clear()
pr.enable()
[occhecker(login) for login in logins_list] # цикл с "оптимизацией"
pr.disable()
pr.print_stats()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment