Last active
August 29, 2015 13:57
-
-
Save pimiento/9649115 to your computer and use it in GitHub Desktop.
Проверяем с помощью cProfile время выполнения трёх разных способов валидации для большого количества записей
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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