2009-04-05 3 views
3

파이썬에서 compile()에 해당하는 함수를 만들려고하지만 원래 문자열을 다시 얻을 수 있습니다. 모호성을 없애기 위해 comp()와 decomp()의 두 함수를 호출 해 봅시다. 즉Python에서 compile()을 되돌릴 수있는 버전

a = comp("2 * (3 + x)", "", "eval") 
eval(a, dict(x=3)) # => 12 
decomp(a) # => "2 * (3 + x)" 

반환 된 문자열 일 필요는 없다이다 동일 ("2 * (3 + X)"허용 될 수있다),하지만 근본적 있어야 같은 ("2 * X + 6 "은 아닐 것이다). 컴파일에 의해 반환 된 코드 객체에 속성을 설정

  • :

    는 여기에 내가 하지 작업을 수행 것을 시도했다입니다. 코드 객체에 사용자 정의 속성을 설정할 수 없습니다.

  • 서브 클래 싱 코드이므로 속성을 추가 할 수 있습니다. 코드는 하위 클래스화할 수 없습니다.
  • 코드 개체를 원래 문자열에 매핑하도록 WeakKeyDictionary를 설정합니다. 코드 객체는 약하게 참조 될 수 없습니다.

여기 문제, 작업을 수행 내용은 다음과 같습니다

  • 원래의 코드 문자열에 전달 파일 이름이 컴파일하는(). 그러나 실제로 파일 이름을 유지할 수있는 능력이 없어졌습니다.
  • 코드 개체를 문자열에 매핑하는 실제 사전 보관. 컴파일이 거의 발생하지 않기 때문에 메모리가 누수됩니다. 현재 사용중인 경우에는 받아 들일 수 있습니다. gc.get_referrers를 통해 주기적으로 키를 실행할 수 있었고 죽은 것들을 죽일 수있었습니다.
+0

, 요점은 무엇인가? –

답변

6

이것은 일종의 이상한 문제이며, 나의 초기 반응은 당신이하고자하는 일을 성취하기 위해 뭔가 다른 것을하는 것이 더 낫다는 것입니다. 하지만 여전히 흥미로운 질문입니다, 그래서 여기에 내 균열이 있습니다 : 나는 원래 코드 소스를 코드 객체의 사용되지 않는 상수로 만듭니다. 원래 파이썬 소스를 가지고 있기 때문에

import types 

def comp(source, *args, **kwargs): 
    """Compile the source string; takes the same arguments as builtin compile(). 
    Modifies the resulting code object so that the original source can be 
    recovered with decomp().""" 
    c = compile(source, *args, **kwargs) 
    return types.CodeType(c.co_argcount, c.co_nlocals, c.co_stacksize, 
     c.co_flags, c.co_code, c.co_consts + (source,), c.co_names, 
     c.co_varnames, c.co_filename, c.co_name, c.co_firstlineno, 
     c.co_lnotab, c.co_freevars, c.co_cellvars) 

def decomp(code_object): 
    return code_object.co_consts[-1] 

>>> a = comp('2 * (3 + x)', '', 'eval') 
>>> eval(a, dict(x=3)) 
12 
>>> decomp(a) 
'2 * (3 + x)' 
4

내 접근 방식은 다른 개체에 코드 개체를 래핑하는 것입니다. 이런 식으로 뭔가 : 당신은 코드 개체 자체를 필요할 때마다

class CodeObjectEnhanced(object): 
    def __init__(self, *args): 
     self.compiled = compile(*args) 
     self.original = args[0] 
def comp(*args): 
    return CodeObjectEnhanced(*args) 

그런 다음, 당신이 a.compiled 사용하고, 원본을 필요할 때마다, 당신은 a.original 사용합니다. 새로운 클래스를 일반 코드 객체처럼 취급하여 eval (self.compiled)을 호출하도록 함수를 리디렉션하는 방법이있을 수 있습니다.

이 장점 중 하나는 원래 문자열이 코드 개체와 동시에 삭제된다는 것입니다. 그러나 당신은 이것을 수행합니다. 원래의 문자열을 저장하는 것이 아마 가장 좋은 접근법 일 것입니다. 근사치가 아니라 정확한 문자열로 끝나는 것입니다.

관련 문제