2013-05-09 3 views
-2

나는 매우 간단한 파이썬 코드로 exec를 사용하고 호출 대신 함수를 호출하려고한다.어떻게 파이썬에서 exec를 사용하여 함수 호출을 나열 할 수 있습니까?

호출 할 함수를 알고있는 경우 명명 된 함수를 print으로 정의하는 사전을 만들고이를 exec의 두 번째 인수로 사용할 수 있습니다.

내가 의 getItem을 overwritting에 의해 호출되는 함수를 인쇄하는 사용자 지정 사전 클래스를 사용하려고 해요

하지만 exec는 발행하여 도움이되지 않습니다

TypeError: exec: arg 2 must be a dictionary or None 

A의 함수 호출을 사용자 정의 할 수있는 방법이 있나요 일반적인 방법?

편집는 :

user('foo') 
password('foo123') 
home('/home/foo') 

user('bar') 
password('bar123') 
home('/home/foo') 

내가 그 안에 포함 된 정보를이 파일을 실행하고 인쇄해야합니다

예를 들어

, 내가 파이썬으로 작성된 다음과 같은 구성 파일을 가지고 가정합니다. 나는 다음과 같은 파이썬 프로그램이 작업을 수행 할 수 있습니다

d = { 'user': print, 'password': print, 'home: 'print } 
execfile(filename, d, {}) 

이 방법의 문제는 내가 파일에 존재하는 모든 기능 d를 초기화해야한다는 것입니다. 나는 getitem에서 뭔가 다른 것을 한 사용자 정의 사전을 사용하려고 시도하고 위의 TypeError을 얻었다.

+1

후 일부 코드 바랍니다 –

+4

내가 3 번을 읽고 난 아직도 혼란 스러워요. 너 뭐하려고? – CppLearner

+2

이것이 해결책 인 실제 문제는 무엇입니까? –

답변

3

아마도 다음과 유사할까요?

class Printer(dict): 
    def __missing__(self, key): 
     def wrapped(*args, **kwargs): 
      print('{} called: args={}, kwargs={}'.format(key, args, kwargs)) 
     return wrapped 

code = ''' 
foo() 
bar(1, 2, baz=3) 
''' 

exec(code, Printer()) 

출력 :

foo called: args=(), kwargs={} 
bar called: args=(1, 2), kwargs={'baz': 3} 
+2

이것은 OP의 직접적인 질문 "일반적인 방법으로 함수 호출을 사용자 정의하는 방법이 있습니까?"에 대한 대답입니다. 꽤 멋지 네요. 그리고'Printer .__ init__'이'globals()'를 잡아줌으로써'__missing__'이 실제 함수를 불러오고 호출 할 수 있도록 확장시킬 수도 있습니다. 함수로 불리는 표현식,'exec' 블록 내에서 정의 된 새로운 함수 등은 여전히 ​​놓치 겠지만 적어도 간접적으로 호출되는 함수는 잡아낼 것입니다. – abarnert

+0

그게 정확히 내가하려고했던거야! 감사! – Penz

3

내가 잘못 될 수도 있지만 그것은 당신이 원하는 것 같아은 다음과 같습니다

>>> the_functions_called_in('foo(); bar() + 4; lol(hello())') 
['foo', 'bar', 'lol', 'hello'] 
이 경우

보다는 exec 당신이 the ast module 원하는 :

>>> m = ast.parse('foo(); bar() + 4; lol(hello())') 
>>> [x.func.id for x in ast.walk(m) if isinstance(x, ast.Call)] 
['foo', 'lol', 'bar', 'hello'] 

함수에 대한 인수가 저장됩니다 args, starargs, keywordskwargs 속성에 ast.Call 개체가 있습니다.

코드를 실제로 실행하고 호출되는 기능 (실행중인 것은 물론)을 추적하려면 profiling을 시도하십시오.

+0

나는 인자가 필요합니다 ... – Penz

+0

@Penz 그것들은 제 편집에서 언급 한'Call' 객체의 속성에 저장됩니다. – Dougal

+1

물론''baz = foo; baz는'foo'보다는'baz'가 호출되었다고 말할 것이고,''eval ("foo()")로 시도하면 foo가 호출되었다는 것을 알지 못할 것입니다 , 등등. 이것이 당신이하려는 일이라면, 제대로 쓰는 것은 불가능합니다. Dougal의 버전은 사용자가 얻을 수있는만큼 가깝기 때문에 간단한 탐색 목적으로는 유용 할 수 있지만 더 강력하게 만들려는 시도는 매우 나쁜 생각입니다. – abarnert

관련 문제