Python 未知模式查找

0 投票
2 回答
502 浏览
提问于 2025-04-16 19:26

好的,简单来说,我想通过重用代码来压缩一个文件,然后在运行时替换缺失的代码。我现在的做法很丑陋而且速度慢,虽然至少能用。问题是这个文件没有特定的结构,比如'aGVsbG8=\n',这是一个base64编码的例子。我的函数速度很慢,因为文件长度超过1700,而且它是逐个字符检查模式的。请帮我提供一些更好的代码,或者至少帮我优化一下我现有的代码。任何有帮助的建议都很欢迎!顺便说一下,我已经尝试过压缩库,但它们的压缩效果没有我这个丑陋的函数好。

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 个回答

1

通常情况下,人们会先把程序通过一个专门为文本优化的压缩算法进行压缩,然后再用 exec 来执行它,比如:

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

可能 .pyc.pyo 文件已经被压缩过了。你可以通过创建一个简单的文件来检查,比如用 x="""aaaaaaaa""",然后逐渐增加长度,比如 x="""aaaaaaaaaaaaaaaaaaaaaaa...aaaa""",看看文件大小是否有明显变化。

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" 和很多其他字符串时会崩溃。)

撰写回答