Python Неизвестный поиск паттернов

Хорошо, в основном я хочу сжать файл, повторно используя код, а затем во время выполнения заменить отсутствующий код. То, что я придумал, действительно ужасно и медленно, по крайней мере, это работает. Проблема в том, что файл не имеет определенной структуры, например, 'aGVsbG8=\n', поскольку вы можете видеть его кодировку base64. Моя функция действительно медленная, потому что длина файла составляет 1700+, и она проверяет шаблоны на 1 символ за раз. Пожалуйста, помогите мне с новым лучшим кодом или, по крайней мере, помогите мне оптимизировать то, что я получил:). Добро пожаловать! Кстати, я уже пробовал библиотеки сжатия, но они не сжимали так хорошо, как моя уродливая функция.

def c_long(inp, cap=False, b=5):
    import re,string
    if cap is False: cap = len(inp)
    es = re.escape; le=len; ref = re.findall; ran = range; fi = string.find
    c = b;inpc = inp;pattern = inpc[:b]; l=[]
    rep = string.replace; ins = list.insert
    while True:
        if c == le(inpc) and le(inpc) > b+1: c = b; inpc = inpc[1:]; pattern = inpc[:b]
        elif le(inpc) <= b: break
        if c == cap: c = b; inpc = inpc[1:]; pattern = inpc[:b]
        p = ref(es(pattern),inp)
        pattern += inpc[c]
        if le(p) > 1 and le(pattern) >= b+1:
            if l == []: l = [[pattern,le(p)+le(pattern)]]
            elif le(ref(es(inpc[:c+2]),inp))+le(inpc[:c+2]) < le(p)+le(pattern):
                x = [pattern,le(p)+le(inpc[:c+1])]
                for i in ran(le(l)):
                    if x[1] >= l[i][1] and x[0][:-1] not in l[i][0]: ins(l,i,x); break
                    elif x[1] >= l[i][1] and x[0][:-1] in l[i][0]: l[i] = x; break
                inpc = inpc[:fi(inpc,x[0])] + inpc[le(x[0]):]
                pattern = inpc[:b]
                c = b-1
        c += 1
    d = {}; c = 0
    s = ran(le(l))
    for x in l: inp = rep(inp,x[0],'{%d}' % s[c]); d[str(s[c])] = x[0]; c += 1
    return [inp,d]

def decompress(inp,l): return apply(inp.format, [l[str(x)] for x in sorted([int(x) for x in l.keys()])])

2 ответа

Самый простой способ сжать данные в кодировке base64- сначала преобразовать их в двоичные данные - это уже сэкономит 25 процентов пространства хранения:

>>> s = "YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXo=\n"
>>> t = s.decode("base64")
>>> len(s)
37
>>> len(t)
26

В большинстве случаев вы можете сжать строку еще дальше, используя некоторый алгоритм сжатия, например t.encode("bz2") или же t.encode("zlib"),

Несколько замечаний о вашем коде: Есть много факторов, которые делают код трудным для чтения: непоследовательный пробел, чрезмерно длинные строки, бессмысленные имена переменных, недиоматический код и т. Д. Пример: Ваш decompress() функция может быть эквивалентно написана как

def decompress(compressed_string, substitutions):
    subst_list = [substitutions[k] for k in sorted(substitutions, key=int)]
    return compressed_string.format(*subst_list)

Теперь уже гораздо более очевидно, что он делает. Вы могли бы пойти еще дальше: почему substitutions словарь со строковыми ключами "0", "1" так далее.? Мало того, что странно использовать строки вместо целых чисел - вам вообще не нужны ключи! Простой список подойдет, и decompress() упростит до

def decompress(compressed_string, substitutions):
    return compressed_string.format(*substitutions)

Вы можете подумать, что все это второстепенно, но если вы сделаете остальную часть своего кода одинаково читабельной, вы сами обнаружите ошибки в своем коде. (Есть ошибки - это сбой для "abcdefgabcdefg" и много других строк.)

Обычно можно прокачать программу через алгоритм сжатия, оптимизированный для текста, а затем запустить его через execнапример,

code="""..."""
exec(somelib.decompress(code), globals=???, locals=???)

Это может быть тот случай, когда .pyc/.pyo файлы уже сжаты, и это можно проверить, создав файл с x="""aaaaaaaa""", затем увеличивая длину до x="""aaaaaaaaaaaaaaaaaaaaaaa...aaaa""" и увидеть, если размер заметно меняется.

Другие вопросы по тегам